/** @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_adc.h"
#include "HL_sys_dma.h"
#include "HL_rti.h"

#define RAW_SIZE 256U
#define MAX_DMA_TRANSFER_CNT 128U

#define ADC1_GE_DMA_REQ DMA_REQ7
#define ADC1_GE_DMA_CHAN DMA_CH3

// DMA transfer count tracker -- these request lines are HET and MIBSPI4/5
#define ADC1_GE_COUNT_DMA_REQ DMA_REQ24
#define ADC1_GE_COUNT_DMA_CHAN DMA_CH24

/**
 *  @brief Circular buffer for DMA sampling
 */
typedef struct SampleCircBuf_t
{
    volatile uint32_t bufferRawADC[RAW_SIZE];
    volatile uint8_t writePtr;
    uint8_t head;
} SampleCircBuf_t;

static const dmaRequest_t dmaReqlineAdcGE = ADC1_GE_DMA_REQ;
static const dmaRequest_t dmaReqlineAdcGECount = ADC1_GE_COUNT_DMA_REQ;
static const dmaChannel_t adcGEDmaChan = ADC1_GE_DMA_CHAN;
static const dmaChannel_t adcGECountDmaChan = ADC1_GE_COUNT_DMA_CHAN;

static g_dmaCTRL adcGEDmaCtrl;
static g_dmaCTRL adcGECountDmaCtrl;

#pragma SET_DATA_SECTION(".sharedRAM")
// Each index is a count, assume when the pointer to this is incremented by DMA that 2 conversions took place
static const uint8_t dmaWriteCnt[MAX_DMA_TRANSFER_CNT] = {
    0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
    32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
    64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94,
    96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126,
    128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158,
    160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190,
    192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222,
    224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254
};
static SampleCircBuf_t adcSampleBuffers[2U];

#pragma SET_DATA_SECTION()


static void configureAdcDma(void);
/* 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) */
    rtiInit();
    adcInit();

    // Set ADC to not be interrupt but DMA controlled
    // Set block size to 2, enable block DMA transfer. 2 for 1 samples per channel per conversion in the group which is 2 channels
//    adcREG1->EVDMACR = (2U << 16U) | (1U << 2U);
//    adcREG1->G1DMACR = (2U << 16U) | (1U << 2U);
    adcREG1->EVDMACR = (1U << 3U);
    adcREG1->G1DMACR = (1U << 3U);

    configureAdcDma();

    // RTI is the trigger for the ADC.
    rtiEnableNotification(rtiREG1, rtiNOTIFICATION_COMPARE0); // Enable interrupt for counter 0
    rtiStartCounter(rtiREG1, rtiCOUNTER_BLOCK0); // Enable counter 0

    // Start ADC conversion only once to trigger the DMA the first time
    adcStartConversion(adcREG1, adcGROUP0);
    adcStartConversion(adcREG1, adcGROUP1);

    for(;;)
    {
        // TODO check adcSampleBuffers at an interval
    }
/* USER CODE END */

    return 0;
}


/* USER CODE BEGIN (4) */

static void configureAdcDma(void)
{
    // ADC Group Event specific settings
//    adcGEDmaCtrl.CHCTRL = ADC1_GE_COUNT_DMA_CHAN+1U; // Chain to a DMA channel to keep track of DMA transfers
    adcGEDmaCtrl.CHCTRL = 0U;
    adcGEDmaCtrl.ELCNT = 2U;
    adcGEDmaCtrl.FRCNT = MAX_DMA_TRANSFER_CNT;
    adcGEDmaCtrl.ELSOFFSET = 0;
    adcGEDmaCtrl.FRSOFFSET = 0;
    adcGEDmaCtrl.ELDOFFSET = 8;               // Destination offset per element (4 bytes * 2 samples = 8 bytes)
    adcGEDmaCtrl.FRDOFFSET = (uint32_t)-1024; // Wrap-around when reaching the end of the 256-element buffer (1024 bytes, not 1024 32-bit values)
    adcGEDmaCtrl.RDSIZE = ACCESS_32_BIT;      // Read whole register contents
    adcGEDmaCtrl.WRSIZE = ACCESS_32_BIT;      // Write whole register contents
    adcGEDmaCtrl.TTYPE = FRAME_TRANSFER;      // Trigger sends frame
    adcGEDmaCtrl.AUTOINIT = AUTOINIT_ON;      // Control Sending / auto transfer to loop back around
    adcGEDmaCtrl.SADD = (uint32_t)(&adcSampleBuffers[0].bufferRawADC);
    adcGEDmaCtrl.DADD = (uint32_t)(&(adcREG1->GxBUF[adcGROUP0]));
    adcGEDmaCtrl.PORTASGN = PORTB_READ_PORTA_WRITE; // RAM read, Peripheral Write
    adcGEDmaCtrl.ADDMODERD = ADDR_FIXED;            // Always reads from same buffer location
    adcGEDmaCtrl.ADDMODEWR = ADDR_OFFSET;           // Increment through circular buffer by 2 elements each time

    // ADC GE DMA counter specific settings
//    adcGECountDmaCtrl.CHCTRL = 0U; // End of chain
//    adcGECountDmaCtrl.ELCNT = 1U;
//    adcGECountDmaCtrl.FRCNT = 1U;
//    adcGECountDmaCtrl.ELSOFFSET = 0;
//    adcGECountDmaCtrl.FRSOFFSET = 0;
//    adcGECountDmaCtrl.ELDOFFSET = 0;
//    adcGECountDmaCtrl.FRDOFFSET = 0;
//    adcGECountDmaCtrl.RDSIZE = ACCESS_8_BIT;
//    adcGECountDmaCtrl.WRSIZE = ACCESS_8_BIT;
//    adcGECountDmaCtrl.TTYPE = FRAME_TRANSFER;
//    adcGECountDmaCtrl.AUTOINIT = AUTOINIT_OFF;
//    adcGECountDmaCtrl.SADD = (uint32_t)(&dmaWriteCnt);
//    adcGECountDmaCtrl.DADD = (uint32_t)(&adcSampleBuffers[0].writePtr);
//    adcGECountDmaCtrl.PORTASGN = PORTA_READ_PORTA_WRITE; // RAM read, RAM Write
//    adcGECountDmaCtrl.ADDMODERD = ADDR_INC1;             // Increment through counter array
//    adcGECountDmaCtrl.ADDMODEWR = ADDR_FIXED;            // Always update writePtr

    // Pull DMA out of reset
    dmaEnable();

    // Assign hardware defined request line to the software defined DMA channel. The channel is arbitrary, the request
    // must align with the devices data sheet for DMA.
    dmaReqAssign(adcGEDmaChan, dmaReqlineAdcGE);
//    dmaReqAssign(adcGECountDmaChan, dmaReqlineAdcGECount);

    // Configure the DMA control packet
    dmaSetCtrlPacket(adcGEDmaChan, adcGEDmaCtrl);
//    dmaSetCtrlPacket(adcGECountDmaChan, adcGECountDmaCtrl);

    // Highest DMA priority
    dmaSetPriority(adcGEDmaChan, HIGHPRIORITY);
//    dmaSetPriority(adcGECountDmaChan, HIGHPRIORITY);

    // Enable DMA triggers
    dmaSetChEnable(adcGEDmaChan, DMA_HW);
//    dmaSetChEnable(adcGECountDmaChan, DMA_HW);
}
/* USER CODE END */
