/**
  *****************************************************************************************************
  * @file    main.c
  * @author  Kiwi Software Team
  * @brief   This example code demonstrates how ADC works.
  *
  * Copyright (c) 2024, Kiwi Instruments Co,. Ltd.
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *
  *   2. 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.
  *
  *   3. Neither the name of the copyright holder 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.
  *****************************************************************************************************
  */

#include "main.h"
#include "kpm32xx_demoboard_ddl.h"


volatile uint32_t ebusSoc0Flag = 0;
volatile uint32_t compareHighFlag = 0;
volatile uint32_t compareLowFlag = 0;


EBUS_Init_T pEBusStruct;


#if defined (__DEBUG_CONSOLE_PRINT__)
/**
  * @brief  This function is implemented for UART print PinMux configuration.
  * @param  None
  * @retval None
  */
void DebugConsole_PinMux_Config(void)
{
	/* SCI1 UART Tx */
	DDL_GPIO_Config2AltFunc(GPIOA, GPIO_PIN_7, GPIOA7_AF1_SCI1_TX_SDA_MOSI);
}
#endif


/**
  * @brief  This function is implemented for ADC0 PinMux configuration.
  * @param  None
  * @retval None
  */
void ADC_PinMux_Config(void)
{
	/* ADC0 channel 5 : GPIOD6 */
	DDL_GPIO_Config2Analog(GPIOD, GPIO_PIN_6);
}


/**
  * Init Ebus, use TimerA0 update event for trigger source.
  */
void ADC_Ebus_Init(void)
{
	DDL_EBUS_Instance_Active();

    DDL_EBUS_StructInit(&pEBusStruct);
	pEBusStruct.syncMode = EBUS_CHN_SYNC_MODE;
	pEBusStruct.detSrc = EBUS_CHN_DETSRC_RISING;
	pEBusStruct.mstrSrc = EBUS_CHN_MSTR_TIMA0_TRGO;
	DDL_EBUS_Init(EBUS, &pEBusStruct);
}


/**
  * Init TimerA0, it will generate an update event every 100ms.
  */
void timerA0_master_init(void)
{
	TIMA_BaseInit_T tmrStruct;

	DDL_TIMA_Instance_Active(TIMA0);

	/* 200ms, 100MHz clock */
	DDL_TIMA_TMR_StructInit(&tmrStruct);
	tmrStruct.period = 20000;
	tmrStruct.prescaler = 999;
	DDL_TIMA_TMR_Init(TIMA0,&tmrStruct);

	DDL_TIMA_AsMaster_Trgo(TIMA0, TIMA_MASTERMODE_UPDATE);
}


/**
  * @brief  This function is implemented for system clock configuration.
  *         where:
  *         System Clock source            = PLL (HIRC)
  *         System Clock frequency         = 100MHz
  * @param  None
  * @retval None
  */
void SystemClock_Config(void)
{
	RCC_PLLInit_T pllInitStruct    = {0};
	RCC_ClkInit_T rccClkInitStruct = {0};

	DDL_RCC_PllStructInit(&pllInitStruct);
	/* FCLK : 100MHz */
	pllInitStruct.pllPrescaler  = 4;
	if (DDL_RCC_PllConfig(&pllInitStruct) != DDL_OK)
	{
		while(1) ;
	}

	/* Select PLL as system clock source */
	rccClkInitStruct.sysClkSource  = RCC_SYSCLKSOURCE_PLLCLK;
	rccClkInitStruct.sysClkDivider = 0;
	if (DDL_RCC_ClkSrcConfig(&rccClkInitStruct) != DDL_OK)
	{
		while(1) ;
	}
}


/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
	uint8_t cnt = 0;
	uint16_t res = 0;
	ADC_SOCConfig_T socConfig;
	ADC_PPBConfig_T ppbConfig;
	ADC_Init_T adcStruct;

	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
	DDL_Init();
	SystemClock_Config();

	/* To make GPIO active */
	DDL_GPIO_Instance_Active();

#if defined (__DEBUG_CONSOLE_PRINT__)
	DebugConsole_PinMux_Config();
	DDL_SCI_Instance_Active(SCI1);
	DDL_SCIUart_DebugConsole_Init(SCI1);
#endif

	printf("ADC single channel Compare demo start:\n");

	timerA0_master_init();
	ADC_Ebus_Init();

	/* init ADC */
	DDL_ADC_Instance_Active(ADC0);
	ADC_PinMux_Config();

	DDL_ADC_StructInit(&adcStruct);
	DDL_ADC_Init(ADC0, &adcStruct);

	memset(&socConfig, 0, sizeof(ADC_SOCConfig_T));
	socConfig.channel    = ADC_CHANNEL_5;
	socConfig.sampleTime = SAMPLE_12_ADCCLK;
	socConfig.hwTrigger = 1;
	socConfig.ebusChannel = pEBusStruct.channel;
	DDL_ADC_ConfigSOC(ADC0, ADC_SOC0, &socConfig);

	ppbConfig.highThreshold = 500;
	ppbConfig.lowThreshold = 10;
	ppbConfig.soc = ADC_SOC0;
	ppbConfig.calOffset = 0;
	ppbConfig.refOffset = 0;
	ppbConfig.enableTwosComplement = RESET;
	DDL_ADC_ConfigPPB(ADC0, ADC_PPB0, &ppbConfig);
	DDL_ADC_EnablePPBMode(ADC0, ADC_PPB0);

	DDL_ADC_IntEnable(ADC0, ADC_INT_SOC0INTEN);
	NVIC_SetPriority(ADC0_IRQn, __PREEMPT_INTRERRUPT_PRIORITY_0__);
	NVIC_EnableIRQ(ADC0_IRQn);
	DDL_ADC_StartSOC_ByHwTrig(ADC0, ADC_SOC0);

	DDL_TIMA_TMR_Start(TIMA0);

	while (1)
	{
		if (ebusSoc0Flag == 1)
		{
			ebusSoc0Flag = 0;
			res = DDL_ADC_ReadSOCResult(ADC0, ADC_SOC0);
			printf("	SOC (%d) with channel (%d) convert value : 0x%x.\n", ADC_SOC0, ADC_CHANNEL_5, res);

			if (compareHighFlag == 1)
			{
				compareHighFlag = 0;
				printf("	Result compare high match.\n");
			}

			if (compareLowFlag == 1)
			{
				compareLowFlag = 0;
				printf("	Result compare low match.\n");
			}

			cnt++;
			if (cnt > 20)
			{
				break;
			}
		}
	}

	DDL_TIMA_TMR_Stop(TIMA0);
	DDL_ADC_StopSOC_ByHwTrig(ADC0, ADC_SOC0);

	printf("ADC single channel Compare demo end.\n");

	return 0;
}

