/**
  *****************************************************************************************************
  * @file    main.c
  * @author  Kiwi Software Team
  * @brief   This example code demonstrates how TIMH trigger ADC.
  * @note
  *          V1.0.0, 2024/12/20. 
  *
  * 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"


TIMH_ClkInit_T       timhClkStruct  = {0};
TIMH_BaseInit_T	     TIMH0_Handler;
EBUS_Init_T          hebus;
ADC_Init_T           hadc;
ADC_SOCConfig_T      socConfig0;		     
uint32_t             channelData[CHANNEL_NUM_MAX];
volatile uint32_t    ebusSoc0Flag = 0;



#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 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  GPIO init.
 * @param  None
 * @retval None
 */
static void Gpio_Init(void)
{
	/* PC5(TIMH_CH0) & PC8(TIMH_CH0N) */
	DDL_GPIO_Config2AltFunc(GPIOC, GPIO_PIN_5, GPIOC5_AF3_TIMH_CH0);
	DDL_GPIO_Config2AltFunc(GPIOC, GPIO_PIN_8, GPIOC8_AF3_TIMH_CH0N);

	/* ADC0 channel 5 : GPIOD9 */
	DDL_GPIO_Config2Analog(GPIOD, GPIO_PIN_9);
	
	/* PC0 and PC1*/
	DDL_GPIO_Config2Output(GPIOC, GPIO_PIN_0, 0, GPIO_NOPULL);
	DDL_GPIO_Config2Output(GPIOC, GPIO_PIN_1, 0, GPIO_NOPULL);
}


/**
 * @brief  TIMH0(PG0) init
 * @param  None
 * @retval None
 * @note    ___________________________            _
 *         |                           |          |  
 *         |                           |__________|  ...
 *
 *         |<-- dutyCycle:33.27us  --->| 
 *         |<---------  period:40.95us ---------->|
 *
 *                             trgiA ->|
 *            trgiB ->|
 *                         trgiC ->|
 */
void timer0_init(void)
{
	/* Make TIMH active */
	DDL_TIMH_Instance_Activate();
	
	/* Config TIMH's clock by setting general functions register */
	DDL_TIMH_ClkStructInit(&timhClkStruct);
	DDL_TIMH_Clock_Init(&timhClkStruct);	
	
	TIMH0_Handler.dutyCycle         = 0x0CFF;
	TIMH0_Handler.period            = 0x0FFF;
	TIMH0_Handler.trig_xValue.trgiA = 0xCFF;
	TIMH0_Handler.trig_xValue.trgiB = 0x67F;
	TIMH0_Handler.trig_xValue.trgiC = 0xAFF;
	TIMH0_Handler.clockSource       = TIMHx_CLOCKSOURCE_CLK_IN;
	TIMH0_Handler.hrModeEnable      = TIMH_HR_MODE_DISABLE; 
	TIMH0_Handler.outputMode        = TIMH_OUTPUT_COMPLEMENTARY;
	TIMH0_Handler.counterMode       = TIMH_CNT_MODE_INDEPENDENT_EDGE;
	
	DDL_TIMH_Init(TIMH0, &TIMH0_Handler);

	NVIC_SetPriority(TIMH0_IRQn, __PREEMPT_INTRERRUPT_PRIORITY_1__);
	NVIC_EnableIRQ(TIMH0_IRQn);
	DDL_TIMH_IntEnable(TIMH0,TIMH_IT_EOC);

	/* TIMH0_ADCtrige1 init */
	DDL_Event_Output_Config(TIMH_EVENT_A, 1, TIMH_ADC_TRIGGER1, EBUS_SRC_TIMH0);
	
	/* 
	 * tigger point : trgiA
	 * ADTR1PS = 0 ASTR1OFS = 0
	 */
	DDL_TIMH_ADC_Triger_Config( TIMH0,0,0,
								ADC_trg1_TRIGA_EN,ADC_trg1_TRIGB_DIS,ADC_trg1_TRIGC_DIS,
								ADC_trg2_TRIGA_DIS,ADC_trg2_TRIGB_DIS,ADC_trg2_TRIGC_DIS );
}


/**
 * @brief  ebus init.
 * @param  None
 * @retval None
 */
void ebus_init(void)
{
    DDL_EBUS_Instance_Active();
    DDL_EBUS_StructInit(&hebus);
	
	hebus.channel  = EBUS_CHN_0;
	hebus.syncMode = EBUS_CHN_ASYNC_MODE;
	hebus.mstrSrc  = EBUS_CHN_MSTR_TIMH_EVENTA;

	DDL_EBUS_Init(EBUS, &hebus);
}


/**
 * @brief  PC0_ebus.
 * @param  None
 * @retval None
 */
static void Gpio_PC0_Ebus_OutPut(void)
{
	GPIO_Evt_T gpioevt;
	
	gpioevt.pin    = GPIO_PIN_0;
	gpioevt.evtChn = hebus.channel;
	gpioevt.evtAck = EVTACK_OP_TOGGLE;
	/* GPIO PC_0 will toggle by ebus signal which come from ebus master IP */
	DDL_GPIO_EBus_Start(GPIOC, &gpioevt);
}


/**
 * @brief  adc init.
 * @param  None
 * @retval None
 */
void adc_init(void)
{
	DDL_ADC_Instance_Active(ADC0);
	DDL_ADC_StructInit(&hadc);
	
	hadc.resolution = RESOLUTION_12BIT;	
	DDL_ADC_Init(ADC0, &hadc);
}


/**
 * @brief  adc init(adc signal will input by PD9).
 * @param  None
 * @retval None
 */
void ADC_Single_Order_Ebus(void)
{
	uint32_t ebusChannel = 0;

	ebusChannel = hebus.channel;

	/* Config ADC0 channel 2( PD9 ) */
	memset(&socConfig0, 0, sizeof(ADC_SOCConfig_T));
	
	socConfig0.sampleTime  = SAMPLE_8_ADCCLK;
	socConfig0.channel     = ADC_CHANNEL_2;
	socConfig0.hwTrigger   = SET;
	socConfig0.ebusChannel = ebusChannel;
	
	DDL_ADC_ConfigSOC(ADC0, ADC_SOC0, &socConfig0);
	
	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);	
}


/**
 * @brief  demo code.
 * @param  None
 * @retval None
 */
void timh_trigger_to_adc(void)
{
	/* init */
	timer0_init();
	ebus_init();
	Gpio_PC0_Ebus_OutPut();
		
	/* config adc and start adc */
	adc_init();
	ADC_Single_Order_Ebus();
	/* start PWM output whitout interrupt */
	DDL_TIMH_PWM_Start(TIMH0);
	
	/* 
	 * wait for one adc conversion finished and print the value.
	 * then stop adc and deinit adc and ebus.
	 * pwm will keep output.
	 */
	while (ebusSoc0Flag == 0)
	{
		;
	}
	ebusSoc0Flag = 0;

	channelData[0] = DDL_ADC_ReadSOCResult(ADC0, ADC_SOC0);
	printf("	SOC (%d) with channel (%d) convert value : 0x%04x.\n", ADC_SOC0, socConfig0.channel, channelData[0]);
	channelData[0] = 0;

	DDL_ADC_StopSOC_ByHwTrig(ADC0, ADC_SOC0);	

	DDL_ADC_Instance_Deactive(ADC0);
	DDL_EBUS_DeInit(EBUS, &hebus);	
	
	/*
     * after 20ms pwm waveform will shutdown.
	 * you can see PC0 toggled and mark the timing when adc trigger hanppen.	
	 */
	DDL_Delay(20);
	DDL_TIMH_PWM_Stop(TIMH0);
}


/**
  * @brief  Demo main.
  * @param  None
  * @retval None
  * @note
  *         !!More detail of the waveform please refer to : timh\triger_to_adc\doc
  */
int main(void)
{
	/* Reset of all peripherals. */
	DDL_Init();
	DDL_Delay(1000);
	SystemClock_Config();
	
#if defined (__DEBUG_CONSOLE_PRINT__)
	DebugConsole_PinMux_Config();
	DDL_SCI_Instance_Active(SCI1);
	DDL_SCIUart_DebugConsole_Init(SCI1);
	printf("TIMH demo start... \n");
#endif
	
	/* To make GPIO active */
	DDL_GPIO_Instance_Active();
	BSP_LEDx_Init(LED_S2);
	Gpio_Init();
	
	timh_trigger_to_adc();

	while (1)
	{
		/* LED Twinkle */
		BSP_LEDx_Twinkle(LED_S2);
		DDL_Delay(200);
	}
}


/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None  
  * @retval None
  */
void Error_Handler(void)
{
    while (1);
}

