/**
  *****************************************************************************************************
  * @file    main.c
  * @author  Kiwi Software Team
  * @brief   This example code demonstrates how LEB works with FPCI.
  * @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"


void Error_Handler(void);


#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  Pin Configuration
  * @param  None
  * @retval None
  */
static void GpioAF_TIMH_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);
}


/**
  * @brief  Init GPIO (PC1)
  * @param  None
  * @retval None
  */
void Gpio_PC1_Init(void)
{
	DDL_GPIO_Config2Output(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET, GPIO_NOPULL);
}


/**
  * @brief TIMH0 Configuration
  * @param  None
  * @retval None
  */
void timh0_init(void)
{
	TIMH_ClkInit_T    timhClkStruct  = {0};
	TIMH_BaseInit_T   timh0_BaseInit = {0};
	
	/* 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);
	
	/* TIMHx's init struct reset to default value */
	DDL_TIMH_BaseStructInit(&timh0_BaseInit);
	
	/* config TIMH_0's init struct */
	timh0_BaseInit.dutyCycle	     = 0x4FFF;
	timh0_BaseInit.period		     = 0xFFFF;
	timh0_BaseInit.phase		     = 0;
	timh0_BaseInit.trig_xValue.trgiA = 0x4FFF;
	timh0_BaseInit.clockSource	     = TIMHx_CLOCKSOURCE_CLK_IN;
	
	/* Init TIMH_0 to TIMH_2 */
	DDL_TIMH_Init(TIMH0, &timh0_BaseInit);
}


/**
  * @brief  LEB Configuration
  * @param  None
  * @retval None
  */
void LEB_counter_test(void)
{
	TIMH_LEB_T       leb_trg_sel = {0};	
	TIMH_yPCI_Init_T fpciInit    = {0};
	TIMH_Overwrite_T overWrite   = {0};

	/* First step, init TIMH0*/
	timh0_init();
	
	/* Second step, FPCI setup */
	DDL_TIMH_yPCI_StructInit(&fpciInit);
	
	fpciInit.pciSource 	      = PCI_PSS_SOFEWARE;           /* FPCI source */
	fpciInit.sofewarePCI_Mode = SWPCIM_TO_RECV_LOGIC;
	fpciInit.pciAQSS          = PCI_AQSS_LEB_ACTIVE;        /* AQSS : LEB active */
	fpciInit.pciTERM          = PCI_TERM_AUTO_TERMINATE;    
	fpciInit.acceptMode 	  = PCI_ACP_LATCHED;            /* FPCI accept mode : Latched */
	overWrite.faultPwm_H      = 0;                          /* set FPCI overwrite level, Pwm_H = 0 */
	overWrite.faultPwm_L      = 0;                          /* set FPCI overwrite level, Pwm_L = 0 */
	
	DDL_TIMH_FPCI_Setup(TIMH0, &fpciInit, &overWrite);
	
	/*
	 * Final step : config LEB. 
	 * Target LEB : 200us.
	 * Start edge : PWM_H falling edge.
	 * ( ((0.0002(s) * 200,000,000) / 8) - 1 ) << 3 = 0x4E18
	 */
	leb_trg_sel.PWM_H_Fall = LEB_trige_EN;
	leb_trg_sel.PWM_H_Rise = LEB_trige_DIS;
	leb_trg_sel.PWM_L_Fall = LEB_trige_DIS;
	leb_trg_sel.PWM_L_Rise = LEB_trige_DIS;

	DDL_TIMH_LEB_Config(TIMH0, 0x4E18, &leb_trg_sel);
	
	/*start PWM output*/
	DDL_TIMH_PWM_Start(TIMH0);
	DDL_Delay(4);

	/* !! make sure timing that driving signal 1 to FPCI do not exceed LEB time length !!*/
	TIMH0->STAT |= TIMH_PGxSTAT_TRIGA;
	while((TIMH0->STAT & TIMH_PGxSTAT_TRIGA) != TIMH_PGxSTAT_TRIGA);
	TIMH0->STAT |= TIMH_PGxSTAT_TRIGA;

	/* Toggle PA1 to mark the timing when sofeware drive signal 1 to FPCI */
	DDL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);	
	/*drive signal 1 to FPCI, PWM output overwrited*/
	__DDL_F_PCI_SWPCI_SET(TIMH0, 1);
	
	DDL_Delay(1);
	
	/*drive signal 0 to FPCI, PWM output continue*/
	DDL_GPIO_TogglePin(GPIOC,GPIO_PIN_1);
	__DDL_F_PCI_SWPCI_SET(TIMH0, 0);
}


/**
  * @brief Demo main.
  * @param None
  * @retval None
  * @note
  * You will see the waveform like this :
  *    _____                             _____
  * H |     |_____________0_____________|     |__
  *          ___                               __ ...
  * L |_____|   |_________0___________________|   
  *
  *         |   |
  *         |   |-> LEB reach 200us, PCI active signal = 1.
  *         |       
  *         |-> Start edge, PWM_H falling edge.
  *
  *
  *
  *
  * !!More detail of the waveform please refer to : timh\leading_edge_blanking_LEB\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 LEB demo start... \n");
#endif

	/* To make GPIO active */
	DDL_GPIO_Instance_Active();
	BSP_LEDx_Init(LED_S2);
	GpioAF_TIMH_Init();
	Gpio_PC1_Init();
	
	/* test for LEB */
	LEB_counter_test();

	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);
}

