/*
 * The Clear BSD License
 * Copyright 2019 NXP
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted (subject to the limitations in the disclaimer below) provided
 * that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o 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.
 *
 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
 * 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 "board.h"
#include "fsl_gpio.h"
#include "fsl_pit.h"
#include "fsl_port.h"
#include "fsl_uart.h"
#include "pin_mux.h"
#include "freemaster.h"
#include "freemaster_cfg.h"


/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/

uint16_t ui16Ftm1Ch0PfcToffMin;
uint16_t ui16Ftm1Ch0PfcToffMax;
uint16_t ui16PfcDuty;
uint16_t ui16ZcdWindowDis;
uint16_t ui16ZcdWindowEn;
uint8_t ui8CmpHyster;
uint8_t ui8CmpFilter;
uint8_t ui8CmpLevel;
uint16_t ui16Ftm0Modulo;
uint16_t ui16Ftm0Ch0Duty;
uint8_t ui8CmpToFtmTriggerEnable;
uint32_t ui32HwTriggerDisable;
uint32_t ui32HwTriggerEnable;

/*******************************************************************************
 * Code
 ******************************************************************************/

/*!
 * @brief Main function
 */
int main(void)
{
  	__disable_irq();
	
	BOARD_BootClockRUN();
    BOARD_InitPins();
	/* Variables init */
	ui16Ftm0Modulo = 1500;
	ui16PfcDuty = 500;
	ui16ZcdWindowDis = 0;
	ui16ZcdWindowEn = 200;
	ui8CmpLevel = 16;
	ui8CmpToFtmTriggerEnable = 0;
	ui32HwTriggerDisable = 0;
	ui32HwTriggerEnable = FTM_SYNC_TRIG0_MASK | FTM_SYNC_REINIT_MASK;
	
	/* Enable clock to peripherals */
	CLOCK_EnableClock(kCLOCK_Ftm0);
	CLOCK_EnableClock(kCLOCK_Cmp0);
	CLOCK_EnableClock(kCLOCK_Dmamux0);
	CLOCK_EnableClock(kCLOCK_Dma0);
	
	/* UART init */
	uart_config_t config;
    UART_GetDefaultConfig(&config);
    config.baudRate_Bps = 19200;
    config.enableTx = true;
    config.enableRx = true;
    UART_Init(UART0, &config, CLOCK_GetFreq(kCLOCK_CoreSysClk));
	
	/* Comparator init */
    CMP0->CR0 = CMP_CR0_FILTER_CNT(ui8CmpFilter)	/* Filter Sample Count */
			  | CMP_CR0_HYSTCTR(ui8CmpHyster);		/* Comparator hard block hysteresis control */		
    CMP0->DACCR = CMP_DACCR_VOSEL(ui8CmpLevel) 		/* DAC output level */
		        | CMP_DACCR_VRSEL(1)				/* Reference voltage will be VDD */
			    | CMP_DACCR_DACEN(1);				/* Enable DAC */
    CMP0->MUXCR = CMP_MUXCR_PSEL(0)	 				/* Plus is CMP0_IN0 */
		        | CMP_MUXCR_MSEL(7);				/* Minus is CMP0_IN7 ~ 6bit reference */
    CMP0->CR1 = CMP_CR1_EN(1) 						/* Comparator Module Enable */
		      | CMP_CR1_OPE(1)  					/* Output pad enable */
		      | CMP_CR1_INV(1);						/* Inverts the comparator output */
	
	/* FTM0 match will trigger FTM1 */
	//SIM->SOPT4 |= SIM_SOPT4_FTM0TRG0SRC_MASK;
		
	/* FlexTimer 0 init */
	FTM0->CONF	= FTM_CONF_BDMMODE(0x3);  		
	FTM0->FMS=0x00;  
	FTM0->MODE |= FTM_MODE_WPDIS_MASK				/* Write protect disable */
			   |  FTM_MODE_FTMEN_MASK;				/* Flextimer mode */		
	FTM0->MOD = ui16Ftm0Modulo;						/* Set modulo */
	FTM0->CONTROLS[0].CnSC = FTM_CnSC_ELSB_MASK		/* Edge aligned PWM CH0 - clear on match */
		                   | FTM_CnSC_MSB_MASK;		/* Edge aligned PWM CH0- clear on match */
	FTM0->CONTROLS[1].CnSC = FTM_CnSC_ELSA_MASK		/* Toggle out for debug */
		                   | FTM_CnSC_MSA_MASK		/* Toggle out for debug */
						   | FTM_CnSC_CHIE_MASK		/* ISR enable for DMA */
						   | FTM_CnSC_DMA_MASK;		/* DMA enable */
	FTM0->CONTROLS[2].CnSC = FTM_CnSC_ELSA_MASK		/* Toggle out for debug */
		                   | FTM_CnSC_MSA_MASK		/* Toggle out for debug */
						   | FTM_CnSC_CHIE_MASK		/* ISR enable for DMA */
						   | FTM_CnSC_DMA_MASK;		/* DMA enable */
	
	FTM0->COMBINE = FTM_COMBINE_SYNCEN0_MASK 		/* CH0 Sync enable */ 
		          | FTM_COMBINE_SYNCEN1_MASK 
				  | FTM_COMBINE_SYNCEN2_MASK;
	
	FTM0->CONTROLS[0].CnV = ui16PfcDuty;							/* CH0 compare val */
	FTM0->CONTROLS[1].CnV = ui16ZcdWindowDis;						/* CH1 compare val */
	FTM0->CONTROLS[2].CnV = ui16PfcDuty + ui16ZcdWindowEn;			/* CH2 compare val */
	FTM0->CNTIN=0x00;								/* Counter init val */
	FTM0->SYNC = FTM_SYNC_TRIG0_MASK				/* Enable the HW TRIG CMP0 */
		       | FTM_SYNC_REINIT_MASK;				/* Reinit on trigger */
	FTM0->SYNCONF |= FTM_SYNCONF_HWWRBUF_MASK		/* HW trigger enable */
		 	      |  FTM_SYNCONF_HWRSTCNT_MASK
				  |  FTM_SYNCONF_HWTRIGMODE_MASK
				  |  FTM_SYNCONF_SYNCMODE_MASK;	
	/*
	FTM0->EXTTRIG |= FTM_EXTTRIG_CH1TRIG_MASK		
				  |  FTM_EXTTRIG_CH2TRIG_MASK;
				  */
	FTM0->SC = FTM_SC_CLKS(0x1);					/* By selecting clock FTM starts count */
	FTM0->PWMLOAD = FTM_PWMLOAD_LDOK_MASK;			/* Load OK - update compare, modulo registers */
	
	

	/* DMA INIT */
    DMAMUX->CHCFG[0] = DMAMUX_CHCFG_ENBL_MASK
		             | DMAMUX_CHCFG_SOURCE(21); 			/* FTM0 CH1 match */				
    DMAMUX->CHCFG[1] = DMAMUX_CHCFG_ENBL_MASK
		             | DMAMUX_CHCFG_SOURCE(22);  			/* FTM0 CH2 match */			
    DMA0->TCD[0].SADDR = (uint32_t)&ui32HwTriggerDisable;	/* Source address */ 					
    DMA0->TCD[1].SADDR = (uint32_t)&ui32HwTriggerEnable; 	/* Source address */					
    DMA0->TCD[0].SOFF = 0x00; 						    	/* Source address offset */
    DMA0->TCD[1].SOFF = 0x00; 								/* Source address offset */
    DMA0->TCD[0].SLAST = 0x00;   										
    DMA0->TCD[1].SLAST = 0x00;   									
    DMA0->TCD[0].DADDR = (uint32_t)&FTM0->SYNC; 			/* Dest address */	
    DMA0->TCD[1].DADDR = (uint32_t)&FTM0->SYNC; 			/* Dest address */	
    DMA0->TCD[0].DOFF = 0x00; 								/* Dest address offset */					
    DMA0->TCD[1].DOFF = 0x00; 								/* Dest address offset */		
    DMA0->TCD[0].DLAST_SGA = (uint32_t)0;
    DMA0->TCD[1].DLAST_SGA = (uint32_t)0;
    DMA0->TCD[0].NBYTES_MLNO = 4; 							/* Num of bytes */
    DMA0->TCD[1].NBYTES_MLNO = 4; 							/* Num of bytes  */
	DMA0->TCD[0].CITER_ELINKNO = 0x0001;					/* One major loop */
	DMA0->TCD[1].CITER_ELINKNO = 0x0001; 					/* One major loop */
    DMA0->TCD[0].BITER_ELINKNO = 0x0001; 					/* One major loop */
    DMA0->TCD[1].BITER_ELINKNO = 0x0001;					/* One major loop */
    DMA0->TCD[0].ATTR =  DMA_ATTR_SSIZE(0x02)
		               | DMA_ATTR_DSIZE(0x02);				/* Source size(words) dest size(words) */ 
	DMA0->TCD[1].ATTR =  DMA_ATTR_SSIZE(0x02)
		               | DMA_ATTR_DSIZE(0x02);				/* Source size(words) dest size(words) */
	DMA0->TCD[0].CSR = 0;
	DMA0->TCD[1].CSR = 0;
	DMA0->ERQ = DMA_ERQ_ERQ0_MASK | DMA_ERQ_ERQ1_MASK;		/* Enable requests */
	
	/* SysTick init */
	SysTick_Config(BOARD_BOOTCLOCKRUN_CORE_CLOCK/10);
	NVIC_EnableIRQ(SysTick_IRQn);
	NVIC_SetPriority(SysTick_IRQn, 2);             
	
	FMSTR_Init();
	
	__enable_irq();
	
    while (1)
    {
	  	FMSTR_Poll();
    }
}

void SysTick_Handler()
{
	FTM0->MOD = ui16Ftm0Modulo;					
	FTM0->CONTROLS[0].CnV = ui16PfcDuty;									
	FTM0->CONTROLS[1].CnV = ui16ZcdWindowDis;
	FTM0->CONTROLS[2].CnV = ui16PfcDuty + ui16ZcdWindowEn;
	FTM0->PWMLOAD = FTM_PWMLOAD_LDOK_MASK;
	
	CMP0->DACCR = CMP_DACCR_VOSEL(ui8CmpLevel)		/* Adjust CMP DAC compare value */									
				| CMP_DACCR_VRSEL(1)
				| CMP_DACCR_DACEN(1);		
	CMP0->CR0 = CMP_CR0_FILTER_CNT(ui8CmpFilter)	/* Adjust CMP Filter value */
			  | CMP_CR0_HYSTCTR(ui8CmpHyster);		/* Adjust CMP hysteresis */	

}

