/*********************************************************************************
 * Copyright(C),Ningbo Joyson Preh Car Connect Co.,Ltd.
 * FileName:	Adc.c
 * Author:		Meng Linglei
 * Version:		Ver0.1
 * Date:		2020-12-18
 * Description:
 *
 *********************************************************************************/
/*********************************************************************************
 *                      Include                                                  *
*********************************************************************************/
/********** External Header File **********/
#include "Abstraction/Include/OS_Interface.h"
#include "Cpu.h"
#include "adc_driver.h"

/********** Internal Header File **********/

/*********************************************************************************
 *                      Macro                                                    *
**********************************************************************************/
/* Timeout for PDB in microseconds */
#define PDLY_TIMEOUT 	30UL

#define DMA_CHANNEL0	0
#define DMA_CHANNEL1	1
/*********************************************************************************
 *                      Enum                                                     *
**********************************************************************************/

/*********************************************************************************
 *                      Typedef/Struct                                           *
**********************************************************************************/

/*********************************************************************************
*                       Private variables                                        *
**********************************************************************************/
uint16_t delayValue;
uint16_t buffer[25];
uint16_t value;


/* configuration structures for simple loop transfers */
edma_loop_transfer_config_t loopConfig = {
    .majorLoopIterationCount = 0,
    .srcOffsetEnable = false,
    .dstOffsetEnable = false,
    .minorLoopOffset = 0,
    .minorLoopChnLinkEnable = false,
    .minorLoopChnLinkNumber = 0,
    .majorLoopChnLinkEnable = false,
    .majorLoopChnLinkNumber = 0
};

edma_transfer_config_t transferConfig = {
    .srcAddr = 0,
    .destAddr = 0,
    .srcTransferSize = EDMA_TRANSFER_SIZE_2B,
    .destTransferSize = EDMA_TRANSFER_SIZE_2B,
    .srcOffset= 4,
    .destOffset = 2,
    .srcLastAddrAdjust = 0,
    .destLastAddrAdjust = 0,
    .srcModulo = EDMA_MODULO_OFF,
    .destModulo = EDMA_MODULO_OFF,
    .minorByteTransferCount = 2,
    .scatterGatherEnable = false,
    .scatterGatherNextDescAddr = 0,
    .interruptEnable = true,
    .loopTransferConfig = &loopConfig
};

/*********************************************************************************
 *                      Function prototypes                                      *
**********************************************************************************/
static void ADC0_Init(void);
static void ADC1_Init(void);
static void ADC0_Deinit(void);
static void ADC1_Deinit(void);
static void PDB0_init(void);
static void PDB1_init(void);
static void DMA_Init(void);
/*********************************************************************************
 *                      Function                                                 *
**********************************************************************************/
/*********************************************************************************
 * Function:		Adc_Init
 * Description:		Analog-to-Digital Converter initialization.
 * Input:			void
 * Output:			-
 * Return:			void
 *********************************************************************************
 * History:			No.		Date		Author			Modification
 *--------------------------------------------------------------------------------
 *					0001	2020-12-18	MengLinglei		New
 *
 **********************************************************************************/
void ADC_Init(void)
{
	ADC1_Init();

	PDB1_init();

	DMA_Init();
#if 1
	// Initialize TRGMUX to route LPIT0 ch0 trigger to both PDBs and PDB's OUT pulse to TRGMUX out7
	TRGMUX_DRV_Init(INST_TRGMUX1, &trgmux1_InitConfig0);

	// Initialize LPIT instance 0. Reset and enable peripheral
	LPIT_DRV_Init(INST_LPIT1, &lpit1_InitConfig);
	// Initialize LPIT channel 0 to generate trigger for PDB via TRGMUX
	LPIT_DRV_InitChannel(INST_LPIT1, 0, &lpit1_ChnConfig0);
	// Start LPIT0 channel 0 counter
	LPIT_DRV_StartTimerChannels(INST_LPIT1, 1);
#endif
}

/*********************************************************************************
 * Function:		Adc_DeInit
 * Description:		Analog-to-Digital Converter release.
 * Input:			void
 * Output:			-
 * Return:			void
 *********************************************************************************
 * History:			No.		Date		Author			Modification
 *--------------------------------------------------------------------------------
 *					0001	2020-12-18	MengLinglei		New
 *
 **********************************************************************************/
void ADC_Deinit(void)
{
	ADC0_Deinit();
	ADC1_Deinit();
}

static void ADC0_Init(void)
{

}

static void ADC1_Init(void)
{
	ADC_DRV_AutoCalibration(INST_ADCONV1);
	ADC_DRV_ConfigConverter(INST_ADCONV1, &adConv1_ConvConfig0);

	ADC_DRV_ConfigChan(INST_ADCONV1, 0UL, &adConv1_ChnConfig0);
	ADC_DRV_ConfigChan(INST_ADCONV1, 1UL, &adConv1_ChnConfig1);
	ADC_DRV_ConfigChan(INST_ADCONV1, 2UL, &adConv1_ChnConfig2);
	ADC_DRV_ConfigChan(INST_ADCONV1, 3UL, &adConv1_ChnConfig3);
	ADC_DRV_ConfigChan(INST_ADCONV1, 4UL, &adConv1_ChnConfig4);
}

static void ADC0_Deinit(void)
{

}

static void ADC1_Deinit(void)
{

}

static void PDB0_init(void)
{

}

static void PDB1_init(void)
{
	PDB_DRV_Init(INST_PDB1, &pdb1_InitConfig0);
	PDB_DRV_Enable(INST_PDB1);

	// config 8 pretriggers on ch0 based on component setting
	PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0UL , &pdb1_AdcTrigInitConfig0);
	PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0UL , &pdb1_AdcTrigInitConfig1);
	PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0UL , &pdb1_AdcTrigInitConfig2);
	PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0UL , &pdb1_AdcTrigInitConfig3);
	PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0UL , &pdb1_AdcTrigInitConfig4);

	// config 1 pretrigger on ch1 based on component setting
	PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 1UL , &pdb1_AdcTrigInitConfig0);

	// set PDB1 counter period to delayValue (~30us)
	PDB_DRV_SetTimerModulusValue(INST_PDB1,(uint32_t) delayValue);
	// set ch0 trigger delay to happen immediate upon Trigger_In 0 (PIT0 ch0)
	PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB1, 0UL , 0UL , (uint32_t) (1));
	// set ch1 trigger0 delay to happen 10us upon Trigger_In 0 (PIT0 ch0)
	PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB1, 1UL , 0UL , (uint32_t) (10*delayValue/PDLY_TIMEOUT));

	PDB_DRV_LoadValuesCmd(INST_PDB1);
}


// DMA channel0 callback
void DMA_ADC0_CHANNEL0(void *parameter, edma_chn_status_t status)
{
	(void)status;
	(void)parameter;

	value = buffer[0];

//    PINS_DRV_SetPins(PTE,1<<14);
//    PINS_DRV_ClearPins(PTE,1<<14);
}

// DMA channel1 callback
void DMA_ADC1_CHANNEL1(void *parameter, edma_chn_status_t status)
{
	(void)status;
	(void)parameter;

	value = buffer[0];

//	PINS_DRV_SetPins(PTE,1<<15);
//	PINS_DRV_ClearPins(PTE,1<<15);
}


/* This function triggers a loop memory-to-memory transfer. */
static void triggerLoopTransfer(uint8_t channel, uint8_t * srcBuff, uint16_t * dstBuff, uint32_t size)
{
	//transferComplete = false;

	dma_request_source_t DmaReq;

    /* configure transfer source and destination addresses */
    transferConfig.srcAddr 				= (uint32_t)srcBuff;
    transferConfig.destAddr 			= (uint32_t)dstBuff;
    transferConfig.srcLastAddrAdjust 	= -(4*size);
    transferConfig.destLastAddrAdjust	= -(2*size);
    loopConfig.majorLoopIterationCount	= size;

    if(channel == 0)
    {
    	DmaReq = EDMA_REQ_ADC0;
    }
    else
    {
    	DmaReq = EDMA_REQ_ADC1;
    }

    /* configure the eDMA channel for a loop transfer (via transfer configuration structure */
    EDMA_DRV_ConfigLoopTransfer(channel, &transferConfig);

    /* select hw request */
    EDMA_DRV_SetChannelRequestAndTrigger(channel, DmaReq, false);

    /* start the channel */
    EDMA_DRV_StartChannel(channel);
}

static void DMA_Init(void)
{
	EDMA_DRV_Init(&dmaController1_State, &dmaController1_InitConfig0, edmaChnStateArray, edmaChnConfigArray, EDMA_CONFIGURED_CHANNELS_COUNT);

	// set DMA ch0 to read first 16 ADC0 Results registers and move it to buffer array starting from 1st element
	triggerLoopTransfer(DMA_CHANNEL0, (uint8_t *)&(ADC0->R[0]),buffer, 16);
	// set DMA ch1 to read first 9 ADC1 Results registers and move it to buffer array starting from 16th element
	triggerLoopTransfer(DMA_CHANNEL1, (uint8_t *)&(ADC1->R[0]),&buffer[16], 9);
}


/* File end */
