/**
  **************************************************************************
  * @file     main.c
  * @version  v2.0.6
  * @date     2021-12-31
  * @brief    main program
  **************************************************************************
  *                       Copyright notice & Disclaimer
  *
  * The software Board Support Package (BSP) that is made available to 
  * download from Artery official website is the copyrighted work of Artery. 
  * Artery authorizes customers to use, copy, and distribute the BSP 
  * software and its related documentation for the purpose of design and 
  * development in conjunction with Artery microcontrollers. Use of the 
  * software is governed by this copyright notice and the following disclaimer.
  *
  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  *
  **************************************************************************
  */

#include "at32f403a_407_clock.h"
#include "at32f403a_407_board.h"

/** @addtogroup UTILITIES_examples
  * @{
  */
	
/** @addtogroup at32f403a_tmr1_tmr2_3adcs 3adcs
  * @{
  */

__IO uint8_t pluse_Period = 4;
__IO uint8_t dma1_trans_complete_flag = 0;
__IO uint8_t dma2_trans_complete_flag = 0;
__IO uint32_t ADC1ConvertedValue[pluse_cnt] = {0};
__IO uint16_t ADC3ConvertedValue[pluse_cnt] = {0};

static void gpio_config(void);
static void dma_config(void);
static void tmr_config(void);
static void adc_config(void);
	
/**
  * @brief  gpio configuration.
  * @param  none
  * @retval none
  */
static void gpio_config(void)
{
  gpio_init_type gpio_initstructure;
	
  /* GPIO clock enable */
  crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);

	/* Configure PC.02, PC.03 and PC.04 (ADC Channel12, ADC Channel13 and  ADC Channel14) as analog inputs */
  gpio_default_para_init(&gpio_initstructure);
  gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
  gpio_initstructure.gpio_pins = GPIO_PINS_2 | GPIO_PINS_3 | GPIO_PINS_4;
  gpio_init(GPIOC, &gpio_initstructure);
}

/**
  * @brief  dma configuration.
  * @param  none
  * @retval none
  */
static void dma_config(void)
{
  dma_init_type dma_init_struct;
	
  /* Enable DMA1 and DMA2 clocks */	
  crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_DMA2_PERIPH_CLOCK, TRUE);
	
  /* Enable the dma Interrupt */	
  nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
  nvic_irq_enable(DMA2_Channel4_5_IRQn, 0, 0);

	/* DMA init config with its default value	*/	
  dma_reset(DMA1_CHANNEL1);
  dma_reset(DMA2_CHANNEL5);
  dma_default_para_init(&dma_init_struct);

	/* DMA1 channel1 configuration */	
  dma_init_struct.buffer_size = pluse_cnt;
  dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  dma_init_struct.memory_base_addr = (uint32_t)ADC1ConvertedValue;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_WORD;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_WORD;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_HIGH;
  dma_init_struct.loop_mode_enable = TRUE;
  dma_init(DMA1_CHANNEL1, &dma_init_struct);
	
	/* DMA2 channel5 configuration */	
  dma_init_struct.memory_base_addr = (uint32_t)ADC3ConvertedValue;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
  dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC3->odt);
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
  dma_init(DMA2_CHANNEL5, &dma_init_struct);

  /* Trigger interrupt enable */
  dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
  dma_interrupt_enable(DMA2_CHANNEL5, DMA_FDT_INT, TRUE);

	/* Enable DMA channel */
  dma_channel_enable(DMA1_CHANNEL1, TRUE);
  dma_channel_enable(DMA2_CHANNEL5, TRUE);
}

/**
  * @brief  tmr1 configuration.
  * @param  none
  * @retval none
  */
static void tmr_config(void)
{
  crm_clocks_freq_type crm_clocks_freq_struct = {0};
	tmr_output_config_type tmr_output_struct;
	
  /* get system clock */
  crm_clocks_freq_get(&crm_clocks_freq_struct);
	
  /* TMR clock enable */
  crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE);
	
	/* Enable the tmr Interrupt */	
  nvic_irq_enable(TMR1_CH_IRQn, 1, 1);
	
  /* TMR1 base configuration
	(systemclock/(systemclock/100000))/100 = 1000Hz(1ms) */
  tmr_base_init(TMR1, pluse_Period*pluse_cnt+20-1, (crm_clocks_freq_struct.sclk_freq/1000/100 - 1));
  tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
  tmr_clock_source_div_set(TMR1, TMR_CLOCK_DIV1);
	
  /* TMR2 base configuration*/	
  tmr_base_init(TMR2, pluse_Period-1, (crm_clocks_freq_struct.sclk_freq/1000/100 - 1));
  tmr_cnt_dir_set(TMR2, TMR_COUNT_UP);
  tmr_clock_source_div_set(TMR2, TMR_CLOCK_DIV1);

  /* primary Configuration in PWM1 Mode */
  tmr_output_default_para_init(&tmr_output_struct);
  tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
  tmr_output_struct.oc_output_state = TRUE;
  tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_LOW;
  tmr_output_struct.oc_idle_state = TRUE;

  /* TMR1 channel 1 */
  tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
  tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_1, pluse_Period*pluse_cnt);

  /* set tmr subordinate synchronization mode */
	tmr_sub_sync_mode_set(TMR1, TRUE);

  /* primary mode selection */
  tmr_primary_mode_select(TMR1, TMR_PRIMARY_SEL_C1ORAW);
	
	/* subordinate Configuration in PWM1 Mode */
  tmr_output_default_para_init(&tmr_output_struct);
  tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
  tmr_output_struct.oc_output_state = TRUE;
  tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_LOW;

	/* TMR2 channel 2 */
  tmr_output_channel_config(TMR2, TMR_SELECT_CHANNEL_2, &tmr_output_struct);
  tmr_channel_value_set(TMR2, TMR_SELECT_CHANNEL_2, pluse_Period/2);
	
	/* TMR2 channel 3 */
  tmr_output_channel_config(TMR2, TMR_SELECT_CHANNEL_3, &tmr_output_struct);
  tmr_channel_value_set(TMR2, TMR_SELECT_CHANNEL_3, pluse_Period/2);	
	
  /* subordinate mode selection */	
	tmr_sub_mode_select(TMR2, TMR_SUB_HANG_MODE);
	tmr_trigger_input_select(TMR2, TMR_SUB_INPUT_SEL_IS0);
	
	/* Trigger interrupt enable */
	tmr_interrupt_enable(TMR2, TMR_C1_INT, TRUE);
}

/**
  * @brief  adc configuration.
  * @param  none
  * @retval none
  */
static void adc_config(void)
{
  adc_base_config_type adc_base_struct;
  /* ADC clock enable */
  crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_ADC2_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_ADC3_PERIPH_CLOCK, TRUE);
  crm_adc_clock_div_set(CRM_ADC_DIV_4);

  /* ADC1 configuration  */
  adc_combine_mode_select(ADC_ORDINARY_SMLT_ONLY_MODE);
  adc_base_default_para_init(&adc_base_struct);
  adc_base_struct.sequence_mode = FALSE;
  adc_base_struct.repeat_mode = FALSE;
  adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
  adc_base_struct.ordinary_channel_length = 1;
	
  adc_base_config(ADC1, &adc_base_struct);
	
	/* ADC1 regular channel configuration */ 
  adc_ordinary_channel_set(ADC1, ADC_CHANNEL_14, 1, ADC_SAMPLETIME_28_5);
  
	/* Enable ADC1 external trigger */ 
  adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_TMR2CH2, TRUE);
	/* Enable ADC1 DMA */
	adc_dma_mode_enable(ADC1, TRUE);

  /* ADC2 configuration  */
  adc_base_config(ADC2, &adc_base_struct);
	
	/* ADC2 regular channel configuration */ 	
  adc_ordinary_channel_set(ADC2, ADC_CHANNEL_13, 1, ADC_SAMPLETIME_28_5);
	/* Enable ADC2 external trigger */ 
  adc_ordinary_conversion_trigger_set(ADC2, ADC12_ORDINARY_TRIG_TMR2CH2, TRUE);

  /* ADC3 configuration  */
  adc_base_config(ADC3, &adc_base_struct);
	
	/* ADC3 regular channel configuration */ 	
  adc_ordinary_channel_set(ADC3, ADC_CHANNEL_12, 1, ADC_SAMPLETIME_28_5);
	/* Enable ADC3 external trigger */ 
  adc_ordinary_conversion_trigger_set(ADC3, ADC3_ORDINARY_TRIG_TMR2CH3, TRUE);
	/* Enable ADC3 DMA */
	adc_dma_mode_enable(ADC3, TRUE);

	/* Enable ADC1 */
  adc_enable(ADC1, TRUE);
	/* Enable ADC2 */	
  adc_enable(ADC2, TRUE);
	
	/* Enable ADC1 reset calibration register */   	
  adc_calibration_init(ADC1);
	/* Check the end of ADC1 reset calibration register */
  while(adc_calibration_init_status_get(ADC1));
	/* Start ADC1 calibration */
  adc_calibration_start(ADC1);
	/* Check the end of ADC1 calibration */
  while(adc_calibration_status_get(ADC1));
	
	/* Enable ADC2 reset calibration register */   	
  adc_calibration_init(ADC2);
	/* Check the end of ADC2 reset calibration register */
  while(adc_calibration_init_status_get(ADC2));
	/* Start ADC2 calibration */
  adc_calibration_start(ADC2);
	/* Check the end of ADC2 calibration */
  while(adc_calibration_status_get(ADC2));

	/* Enable ADC3 */
  adc_enable(ADC3, TRUE);
	/* Enable ADC3 reset calibration register */   
  adc_calibration_init(ADC3);
	/* Check the end of ADC3 reset calibration register */
  while(adc_calibration_init_status_get(ADC3));
	/* Start ADC3 calibration */
  adc_calibration_start(ADC3);
	/* Check the end of ADC3 calibration */
  while(adc_calibration_status_get(ADC3));
}

/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{

  nvic_priority_group_config(NVIC_PRIORITY_GROUP_2);

  /* system clocks configuration */
  system_clock_config();

  /* gpio configuration */
  gpio_config();

	/* uart configuration */
  uart_print_init(115200);

	/* board initialize interface init led and button */
  at32_board_init();
	
	gpio_config();
	
  tmr_config();
	
  dma_config();
	
  adc_config();	

  printf("triple_adc_synchro_trigger \r\n");

  /* enable tmr2 */
  tmr_counter_enable(TMR2, TRUE);	
  /* output enable */
  tmr_output_enable(TMR1, TRUE);  
  /* enable tmr1 */
  tmr_counter_enable(TMR1, TRUE);

	while(1)
  {
		uint8_t i = 0;		
		dma1_trans_complete_flag = 0;
		dma2_trans_complete_flag = 0;
		while(dma1_trans_complete_flag == 0);
		while(dma2_trans_complete_flag == 0);		

		/* disable tmr1 */
		tmr_counter_enable(TMR1, FALSE);
		
		for(i = 0; i < 20; i++)
		{
			printf("adc1_ordinary_valuetab[%d] = 0x%03x\r\n", i, ADC1ConvertedValue[i]&0x0fff);
			printf("adc2_ordinary_valuetab[%d] = 0x%03x\r\n", i, ADC1ConvertedValue[i]>>16);
			printf("adc3_ordinary_valuetab[%d] = 0x%03x\r\n", i, ADC3ConvertedValue[i]);
			printf("\r\n");
		}

		at32_led_toggle(LED2);
		at32_led_toggle(LED3);
		at32_led_toggle(LED4);
		
		/* enable tmr1 */
		tmr_counter_enable(TMR1, TRUE);
  }
}

/**
  * @}
  */ 

/**
  * @}
  */ 
