/*
 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
 *
 */
/*******************************************************************************
 * Standard C Included Files
 ******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*******************************************************************************
 * SDK Included Files
 ******************************************************************************/
#include "board.h"
#include "fsl_uart_driver.h"
#include "fsl_edma_driver.h"
#include "fsl_device_registers.h"
#include "fsl_debug_uart.h"
/*******************************************************************************
 * Application Included Files
 ******************************************************************************/
#include "data_file.h"
#include "terminal.h"
#include "dspi.h"
#include "edma.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define SPI0_TXCMD (SPI_PUSHR_PCS(0x01) | SPI_PUSHR_CTAS(0x00)) 
/*******************************************************************************
 * Global Variables
 ******************************************************************************/
/* UART Buffers*/
char receiveBuff[32];

/* DMA Buffers */
uint32_t masterRxBuffer[64];
uint8_t g_slaveRxBuffer[256];
volatile uint16_t g_slaveTxCount;
volatile uint32_t g_errorFlag;
/*******************************************************************************
 * Prototypes
 ******************************************************************************/
void pin_setup(void);
/*******************************************************************************
 * Code
 ******************************************************************************/
void pin_setup(void)
{
    configure_spi_pin_mux(kMasterInstance);
    configure_spi_pin_mux(kSlaveInstance);
}
/******************************************************************************/
int main (void)
{  
    int32_t index;
    uint8_t msg;
    uint32_t var;
    
    volatile uint16_t count;
       
    hardware_init();
    dbg_uart_init();
    
    pin_setup();
    
    /* Generate SPI transmit buffer, with SPI TX Commands. */
    uint32_t *spiPush = mem_allocate(sizeof(dataBuffer) * 2);
    memset(spiPush, 0, sizeof(dataBuffer) * 2);
    
    for(index = 0; index < (sizeof(dataBuffer) / 2); index++)
    {
        spiPush[index] = SPI0_TXCMD | dataBuffer[index];
    }
    
    /* Print welcome message & demo configuration to terminal. */
    print_welcome();
    
    print_configuration();
    
    print_pin_setup();
    
    /* Initialize eDMA & DMAMUX */
    edma_init();
    
    /* eDMA Channel 0 Configuration for transmitting data from DSPI0. */
    edma_channel_t dmaCh0;
    
    edma_loop_setup_t *dmaLoop0 = (edma_loop_setup_t *)mem_allocate(sizeof(edma_loop_setup_t));
    
    dmaLoop0->dmaChanNum = DMA_CH0;
    dmaLoop0->dmaCh = &dmaCh0;
    dmaLoop0->type = kEdmaMemoryToPeripheral;
    dmaLoop0->chSource = kDmaRequestMux0SPI0Tx;
    dmaLoop0->srcAddr = (uint32_t)&spiPush[0];
    dmaLoop0->destAddr = (uint32_t)&SPI0->PUSHR;
    dmaLoop0->length = 0x100U;
    dmaLoop0->size = 0x04U;
    dmaLoop0->watermark = 0x04U;
    dmaLoop0->period = 0x01U;
    
    setup_edma_loop(dmaLoop0);
    
    /* eDMA Channel 1 Configuration for receiving data on DSPI0. */
    edma_channel_t dmaCh1;
    
    edma_loop_setup_t *dmaLoop1 = (edma_loop_setup_t *)mem_allocate(sizeof(edma_loop_setup_t));
    
    dmaLoop1->dmaChanNum = DMA_CH1;
    dmaLoop1->dmaCh = &dmaCh1;
    dmaLoop1->type = kEdmaPeripheralToMemory;
    dmaLoop1->chSource = kDmaRequestMux0SPI0Rx;
    dmaLoop1->srcAddr = (uint32_t)&SPI0->POPR;
    dmaLoop1->destAddr = (uint32_t)&masterRxBuffer;
    dmaLoop1->length = 0x100U;
    dmaLoop1->size = 0x04U;
    dmaLoop1->watermark = 0x04U;
    dmaLoop1->period = 0x01U;    
    
    setup_edma_loop(dmaLoop1);
    
    /* eDMA Channel 2 Configuration for receiving data on DSPI1. */   
    edma_channel_t dmaCh2;  
    
    edma_loop_setup_t *dmaLoop2 = (edma_loop_setup_t *)mem_allocate(sizeof(edma_loop_setup_t));
    
    dmaLoop2->dmaChanNum = DMA_CH2;
    dmaLoop2->dmaCh = &dmaCh2;
    dmaLoop2->type = kEdmaPeripheralToMemory;
    dmaLoop2->chSource = kDmaRequestMux0SPI1;
    dmaLoop2->srcAddr = (uint32_t)&SPI1->POPR;
    dmaLoop2->destAddr = (uint32_t)&g_slaveRxBuffer;
    dmaLoop2->length = 0x100U;
    dmaLoop2->size = 0x04U;
    dmaLoop2->watermark = 0x04U;
    dmaLoop2->period = 0x01U;   
    
    setup_edma_loop(dmaLoop2);  
    
    /* DSPI Master Configuration */
    dspi_edma_master_setup(kMasterInstance, 5000, 16);
        
    /* DSPI Slave Configuration */
    dspi_edma_slave_setup(kSlaveInstance, 16);
    
    /* Print out starting contents of g_slaveRxBuffer. */
    printf("\r\ng_slaveRxBuffer\r\n\r\n");
    for(count = 0; count < 64; count++)
    {
        var = g_slaveRxBuffer[(4 * count) + 1];
        var = (var << 8) | (uint16_t)g_slaveRxBuffer[4 * count];
        printf("%08X\t", var);
        if((count + 1) % 4 == 0)
        {
            printf("\r\n");
        }
    }	
	
    /* Print out starting contents of masterRxBuffer. */
    printf("\r\n\r\nmasterRxBuffer\r\n\r\n");
    for(count = 0; count < 64; count++)
    {
        printf("%08X\t", masterRxBuffer[count]);
        if((count + 1) % 4 == 0)
        {
            printf("\r\n");
        }
    }	
	
    printf("\r\n\r\n\r\nPress space bar to begin.\r\n");
    msg = 'A';
    while(msg != ' ')
    {
	#if defined(__ICCARM__)
	    msg = getchar();
	#elif defined(__GNUC__)
        while(!uart_hal_is_receive_data_register_full(BOARD_DEBUG_UART_INSTANCE)) {}
        uart_hal_getchar(BOARD_DEBUG_UART_INSTANCE, (uint8_t *)&msg);	
	#endif	
    }    
    
	printf("\r\nDemo started...\r\n");
	
    /* Enable eDMA channels requests to initiate DSPI transfers. */
    edma_start_channel(dmaLoop2->dmaCh);
    edma_start_channel(dmaLoop1->dmaCh);
    edma_start_channel(dmaLoop0->dmaCh);
    
    while(1)
    {
        if(g_errorFlag == 0x00DEAD00)
        {
            /* Disable eDMA loops. */
            disable_edma_loop(dmaLoop0);
            disable_edma_loop(dmaLoop1);
            disable_edma_loop(dmaLoop2);
            printf("\r\nDemo Complete.\r\n\r\n%d loops completed.\r\n", g_slaveTxCount);
            
            /* Print out new contents of g_slaveRxBuffer. */
            printf("\r\ng_slaveRxBuffer\r\n\r\n");
            for(count = 0; count < 64; count++)
            {
                var = g_slaveRxBuffer[(4 * count) + 1];
                var = (var << 8) | (uint16_t)g_slaveRxBuffer[4 * count];
                printf("%08X\t", var);
                if((count + 1) % 4 == 0)
                {
                    printf("\r\n");
                }
            }
            
            /* Print out new contents of masterRxBuffer. */
            printf("\r\n\r\nmasterRxBuffer\r\n\r\n");
            for(count = 0; count < 64; count++)
            {
                printf("%08X\t", masterRxBuffer[count]);
                if((count + 1) % 4 == 0)
                {
                    printf("\r\n");
                }
            }

            /* Find the maximum value returned to SPI master. */
            var = 0; 
            for(index = 0; index < 64; index++)
            {
                if(masterRxBuffer[index] > var)
                {
                    var = masterRxBuffer[index];
                }
            }
            
            printf("\r\nFinal value received from SPI slave: 0x%X", (uint8_t)(var >> 8));
            printf("\r\nFinal value of g_slaveTxCount sent:  0x%X", g_slaveTxCount - 1);
            
            /* Check if highest value received by SPI Master matches the highest value sent by SPI Slave. */
            if((uint8_t)(var >> 8) == (g_slaveTxCount - 1))
            {
                printf("\r\nSuccess!\r\n");
            }
            else
            {
                printf("\r\nFail... check connections.\r\n");
            }
            
            
            g_errorFlag = 0;            
        } 
    } 
}

/******************************************************************************
 * EOF
 ******************************************************************************/                         
