#include "bsp/bsp_driver.h"
#include "libs/utils.h"

/*
* gpio.c
* all pins used as gpio(in/out/irq) must be init&accessed here
*/

void gpio_pin_init(void){
	crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
}


void gpio_beep(u32 ms) {
}

void at32_gpio_init(gpio_type *gpiox, gpio_mode_type mode, gpio_output_type otype, gpio_pull_type pull, u32 pin) {
	gpio_init_type gpio_init_struct = {0};
	gpio_default_para_init(&gpio_init_struct);
	gpio_init_struct.gpio_mode = mode;
	gpio_init_struct.gpio_out_type = otype;
	gpio_init_struct.gpio_pull = pull;
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	
	/* High-side, Phase A,B,C Config */
	gpio_init_struct.gpio_pins = pin;
	gpio_init(gpiox, &gpio_init_struct);
}


void gpio_mc_brk_init(void) {
#ifdef GPIO_BRAKE_IN_GROUP
	crm_periph_clock_enable(GPIO_BRAKE_IN_RCU, TRUE);
#ifdef GPIO_BRAKE_PIN_REMAP
	gpio_pin_remap_config(GPIO_BRAKE_PIN_REMAP, TRUE);
#endif
	at32_gpio_init(GPIO_BRAKE_IN_GROUP, GPIO_BRAKE_IN_MODE, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_BRAKE_IN_PIN);

	exint_init_type exint_init_struct;

	gpio_exint_line_config(GPIO_BRAKE_EXIT_SRC_GROUP, GPIO_BRAKE_EXIT_SRC_PIN);
	
	exint_default_para_init(&exint_init_struct);
	exint_init_struct.line_enable = TRUE;
	exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
	exint_init_struct.line_select = GPIO_BRAKE_EXTI;
	exint_init_struct.line_polarity = EXINT_TRIGGER_BOTH_EDGE;
	exint_init(&exint_init_struct);
	exint_flag_clear(GPIO_BRAKE_EXTI);
	nvic_irq_enable(GPIO_BRAKE_IRQ, EBREAK_IRQ_PRIORITY, 0U);
#endif
}

void gpio_mlock_init(void) {
#ifdef GPIO_MLOCK_IN_GROUP
	crm_periph_clock_enable(GPIO_MLOCK_IN_RCU, TRUE);
	at32_gpio_init(GPIO_MLOCK_IN_GROUP, GPIO_MLOCK_IN_MODE, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_MLOCK_IN_PIN);
#endif
}

void gpio_fan_det_init(void) {
#ifdef GPIO_FAN1_IN_GROUP
	crm_periph_clock_enable(GPIO_FAN1_IN_RCU, TRUE);
	at32_gpio_init(GPIO_FAN1_IN_GROUP, GPIO_FAN1_IN_MODE, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_FAN1_IN_PIN);
	exint_init_type exint_init_struct;

	gpio_exint_line_config(GPIO_FAN1_EXIT_SRC_GROUP, GPIO_FAN1_EXIT_SRC_PIN);
	
	exint_default_para_init(&exint_init_struct);
	exint_init_struct.line_enable = TRUE;
	exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
	exint_init_struct.line_select = GPIO_FAN1_EXTI;
	exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
	exint_init(&exint_init_struct);
	exint_flag_clear(GPIO_FAN1_EXTI);	
	nvic_irq_enable(GPIO_FAN1_IRQ, ENC_OTHER_IRQ_PRIORITY, 0U);
#endif
}

void gpio_phase_u_detect(bool enable) {
#ifdef GPIO_UDEC_OUT_GROUP
	if (enable) {
		at32_gpio_init(GPIO_UDEC_OUT_GROUP, GPIO_UDEC_OUT_MODE, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_UDEC_OUT_PIN);
	#ifdef GPIO_UDEC_OUT_REMAP_DISABLE
		gpio_pin_remap_config(GPIO_UDEC_OUT_REMAP_DISABLE, ENABLE);
	#endif
		gpio_bits_write(GPIO_UDEC_OUT_GROUP, GPIO_UDEC_OUT_PIN, TRUE);
	}else {
		at32_gpio_init(GPIO_UDEC_OUT_GROUP, GPIO_MODE_INPUT, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_UDEC_OUT_PIN);
	#ifdef GPIO_UDEC_OUT_REMAP_ENABLE
		gpio_pin_remap_config(GPIO_UDEC_OUT_REMAP_ENABLE, ENABLE);
	#endif
	}
#endif
}


void gpio_led_init(void) {
#ifdef GPIO_LED_OUT_GROUP
	crm_periph_clock_enable(GPIO_LED_OUT_RCU, TRUE);
	at32_gpio_init(GPIO_LED_OUT_GROUP, GPIO_LED_OUT_MODE, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_LED_OUT_PIN);
	gpio_bits_reset(GPIO_LED_OUT_GROUP, GPIO_LED_OUT_PIN);
#endif
}

void gpio_brk_light_init(void) {
#ifdef GPIO_BRAKE_LIGHT_OUT_GROUP
	crm_periph_clock_enable(GPIO_BRAKE_LIGHT_OUT_RCU, TRUE);
	at32_gpio_init(GPIO_BRAKE_LIGHT_OUT_GROUP, GPIO_BRAKE_LIGHT_OUT_MODE, GPIO_OUTPUT_PUSH_PULL, GPIO_PULL_NONE, GPIO_BRAKE_LIGHT_OUT_PIN);
	gpio_bits_reset(GPIO_BRAKE_LIGHT_OUT_GROUP, GPIO_BRAKE_LIGHT_OUT_PIN);
#endif
}

void mc_gpio_init(void) {
	gpio_mlock_init();
	gpio_mc_brk_init();
	gpio_fan_det_init();
	gpio_led_init();
	gpio_brk_light_init();
}


void gpio_led_enable(bool enable) {
#ifdef GPIO_LED_OUT_GROUP
	gpio_bits_write(GPIO_BRAKE_LIGHT_OUT_GROUP, GPIO_BRAKE_LIGHT_OUT_PIN, enable?TRUE:FALSE);
#endif
}

void gpio_brk_light_enable(bool enable) {
#ifdef GPIO_BRAKE_LIGHT_OUT_GROUP
	gpio_bits_write(GPIO_BRAKE_LIGHT_OUT_GROUP, GPIO_BRAKE_LIGHT_OUT_PIN, enable?TRUE:FALSE);
#endif
}


bool mc_get_gpio_brake(void) {
	return gpio_input_data_bit_read(GPIO_BRAKE_IN_GROUP, GPIO_BRAKE_IN_PIN) == SET;
}

bool mc_get_gpio_brake1(void) {
#ifdef GPIO_BRAKE1_IN_GROUP
	return gpio_input_data_bit_read(GPIO_BRAKE1_IN_GROUP, GPIO_BRAKE1_IN_PIN) == SET;
#else
	return mc_get_gpio_brake();
#endif
}


bool gpio_motor_locked(void) {
#ifdef GPIO_MLOCK_IN_GROUP
	return gpio_input_data_bit_read(GPIO_MLOCK_IN_GROUP, GPIO_MLOCK_IN_PIN) == RESET;
#else
	return false;
#endif
}

