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

#ifdef GD32_FOC_DEMO
#define IR2136S_Enable_pin 0
#define LED1_Enable_pin 1
#define LED2_Enable_pin 2
#define LED3_Enable_pin 3
#define KEY_Start_pin   4
#define KEY_Stop_pin    5
#define KEY_Func_pin   6
#endif
/*
* gpio.c
* all pins used as gpio(in/out/irq) must be init&accessed here
*/
const static gpio_pin_config_t _pins[] = {
#ifdef GD32_FOC_DEMO
	[IR2136S_Enable_pin] = {GPIOA, GPIO_PIN_12, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, 0},
	[LED1_Enable_pin] = {GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, 0},
	[LED2_Enable_pin] = {0, GPIO_PIN_9, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, 0},
	[LED3_Enable_pin] = {GPIOC, GPIO_PIN_5, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, 0},
	[KEY_Start_pin] = {GPIOB, GPIO_PIN_5, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, 0},
	[KEY_Stop_pin] = {GPIOB, GPIO_PIN_11, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, 0},
#endif	
};
void gpio_pin_init(void){
	rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_GPIOC);
	rcu_periph_clock_enable(RCU_GPIOD);
	rcu_periph_clock_enable(RCU_GPIOF);
	rcu_periph_clock_enable(RCU_AF);
	
	for (int i = 0; i < ARRAY_SIZE(_pins); i++){
		if (_pins[i].init_value != -1){
			gpio_bit_write(_pins[i].group, _pins[i].pin, (bit_status)_pins[i].init_value);
		}
		if (_pins[i].group != 0) {
			gpio_init(_pins[i].group, _pins[i].mode, _pins[i].speed, _pins[i].pin);
		}
	}
#ifdef CONFIG_BEEP
	gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
	gpio_beep(50);
#endif
}


void gpio_beep(u32 ms) {
#ifdef CONFIG_BEEP
	gpio_bit_write(GPIOB, GPIO_PIN_2, SET);
	delay_ms(ms);
	gpio_bit_write(GPIOB, GPIO_PIN_2, RESET);
#endif
}

void gpio_mc_brk_init(void) {
#ifdef GPIO_BRAKE_IN_GROUP
	rcu_periph_clock_enable(GPIO_BRAKE_IN_RCU);
#ifdef GPIO_BRAKE_PIN_REMAP
	gpio_pin_remap_config(GPIO_BRAKE_PIN_REMAP, ENABLE);
#endif
	gpio_init(GPIO_BRAKE_IN_GROUP, GPIO_BRAKE_IN_MODE, GPIO_OSPEED_50MHZ, GPIO_BRAKE_IN_PIN);
	
	gpio_exti_source_select(GPIO_BRAKE_EXIT_SRC_GROUP, GPIO_BRAKE_EXIT_SRC_PIN);
	exti_init(GPIO_BRAKE_EXTI, EXTI_INTERRUPT, EXTI_TRIG_BOTH);
	nvic_irq_enable(GPIO_BRAKE_IRQ, EBREAK_IRQ_PRIORITY, 0U);
	exti_interrupt_flag_clear(GPIO_BRAKE_EXTI);
	exti_interrupt_enable(GPIO_BRAKE_EXTI);	
#endif
#ifdef GPIO_BRAKE1_IN_GROUP
	rcu_periph_clock_enable(GPIO_BRAKE1_IN_RCU);
	gpio_init(GPIO_BRAKE1_IN_GROUP, GPIO_BRAKE1_IN_MODE, GPIO_OSPEED_50MHZ, GPIO_BRAKE1_IN_PIN);

	gpio_exti_source_select(GPIO_BRAKE1_EXIT_SRC_GROUP, GPIO_BRAKE1_EXIT_SRC_PIN);
	exti_init(GPIO_BRAKE1_EXTI, EXTI_INTERRUPT, EXTI_TRIG_BOTH);
	nvic_irq_enable(GPIO_BRAKE1_IRQ, EBREAK_IRQ_PRIORITY, 0U);
	exti_interrupt_flag_clear(GPIO_BRAKE1_EXTI);
	exti_interrupt_enable(GPIO_BRAKE1_EXTI);
#endif
}

void gpio_mlock_init(void) {
#ifdef GPIO_MLOCK_IN_GROUP
	rcu_periph_clock_enable(GPIO_MLOCK_IN_RCU);
	gpio_init(GPIO_MLOCK_IN_GROUP, GPIO_MLOCK_IN_MODE, GPIO_OSPEED_50MHZ, GPIO_MLOCK_IN_PIN);
#endif
}

void gpio_fan_det_init(void) {
#ifdef GPIO_FAN1_IN_GROUP
	rcu_periph_clock_enable(GPIO_FAN1_IN_RCU);
	gpio_init(GPIO_FAN1_IN_GROUP, GPIO_FAN1_IN_MODE, GPIO_OSPEED_50MHZ, GPIO_FAN1_IN_PIN);
	gpio_exti_source_select(GPIO_FAN1_EXIT_SRC_GROUP, GPIO_FAN1_EXIT_SRC_PIN);
	exti_init(GPIO_FAN1_EXTI, EXTI_INTERRUPT, EXTI_TRIG_RISING);
	nvic_irq_enable(GPIO_FAN1_IRQ, ENC_OTHER_IRQ_PRIORITY, 0U);
	exti_interrupt_flag_clear(GPIO_FAN1_EXTI);
	exti_interrupt_enable(GPIO_FAN1_EXTI);
#endif
#ifdef GPIO_FAN2_IN_GROUP
	rcu_periph_clock_enable(GPIO_FAN2_IN_RCU);
	gpio_init(GPIO_FAN2_IN_GROUP, GPIO_FAN2_IN_MODE, GPIO_OSPEED_50MHZ, GPIO_FAN2_IN_PIN);
	gpio_exti_source_select(GPIO_FAN2_EXIT_SRC_GROUP, GPIO_FAN2_EXIT_SRC_PIN);
	exti_init(GPIO_FAN2_EXTI, EXTI_INTERRUPT, EXTI_TRIG_RISING);
	nvic_irq_enable(GPIO_FAN2_IRQ, ENC_OTHER_IRQ_PRIORITY, 0U);
	exti_interrupt_flag_clear(GPIO_FAN2_EXTI);
	exti_interrupt_enable(GPIO_FAN2_EXTI);
#endif
}

void gpio_phase_u_detect(bool enable) {
#ifdef GPIO_UDEC_OUT_GROUP
	if (enable) {
		gpio_init(GPIO_UDEC_OUT_GROUP, GPIO_UDEC_OUT_MODE, GPIO_OSPEED_50MHZ, GPIO_UDEC_OUT_PIN);
	#ifdef GPIO_UDEC_OUT_REMAP_DISABLE
		gpio_pin_remap_config(GPIO_UDEC_OUT_REMAP_DISABLE, ENABLE);
	#endif
		gpio_bit_write(GPIO_UDEC_OUT_GROUP, GPIO_UDEC_OUT_PIN, SET);
	}else {
		gpio_init(GPIO_UDEC_OUT_GROUP, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, 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
	rcu_periph_clock_enable(GPIO_LED_OUT_RCU);
	gpio_init(GPIO_LED_OUT_GROUP, GPIO_LED_OUT_MODE, GPIO_OSPEED_50MHZ, GPIO_LED_OUT_PIN);
	gpio_bit_reset(GPIO_LED_OUT_GROUP, GPIO_LED_OUT_PIN);
#endif
}

void gpio_brk_light_init(void) {
#ifdef GPIO_BRAKE_LIGHT_OUT_GROUP
	rcu_periph_clock_enable(GPIO_BRAKE_LIGHT_OUT_RCU);
	gpio_init(GPIO_BRAKE_LIGHT_OUT_GROUP, GPIO_BRAKE_LIGHT_OUT_MODE, GPIO_OSPEED_50MHZ, GPIO_BRAKE_LIGHT_OUT_PIN);
	gpio_bit_reset(GPIO_BRAKE_LIGHT_OUT_GROUP, GPIO_BRAKE_LIGHT_OUT_PIN);
#endif
}

void gpio_board_id_init(void) {
#ifdef BOOT_PIN_0_GROUP
	gpio_init(BOOT_PIN_0_GROUP, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, BOOT_PIN_0_PIN);
	gpio_init(BOOT_PIN_1_GROUP, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, BOOT_PIN_1_PIN);
#endif
}

u8  gpio_hw_board_id(void) {
	u8 id = BOARD_105_VERSION_4;
#ifdef BOOT_PIN_0_GROUP
	u8 b0 = gpio_input_bit_get(BOOT_PIN_0_GROUP, BOOT_PIN_0_PIN);
	u8 b1 = gpio_input_bit_get(BOOT_PIN_1_GROUP, BOOT_PIN_1_PIN);
	id = ((b1 << 1) | b0);
#endif
	return id;
}

void gpio_repear_key_init(void) {
#ifdef REPEAR_IN_GROUP
	gpio_init(REPEAR_IN_GROUP, REPEAR_IN_MODE, GPIO_OSPEED_50MHZ, REPEAR_IN_PIN);
#endif
}
static u8 _board_id = BOARD_105_VERSION_4;
void mc_gpio_init(void) {
	gpio_mlock_init();
	gpio_mc_brk_init();
	gpio_fan_det_init();
	gpio_led_init();
	gpio_brk_light_init();
	gpio_board_id_init();
	gpio_repear_key_init();
	int count = 10;
	do {
		delay_ms(5);
		_board_id = gpio_hw_board_id();
		if (_board_id == BOARD_105_VERSION_3 || _board_id == BOARD_105_VERSION_4) {
			break;
		}
	}while(count-- > 0);
}

bool gpio_is_repear_mode(void) {
#ifndef REPEAR_IN_GROUP
	return false;
#else
	return gpio_input_bit_get(REPEAR_IN_GROUP, REPEAR_IN_PIN) == RESET;
#endif
}

void gpio_led_enable(bool enable) {
#ifdef GPIO_LED_OUT_GROUP
	gpio_bit_write(GPIO_BRAKE_LIGHT_OUT_GROUP, GPIO_BRAKE_LIGHT_OUT_PIN, enable?SET:RESET);
#endif
}

void gpio_brk_light_enable(bool enable) {
#ifdef GPIO_BRAKE_LIGHT_OUT_GROUP
	gpio_bit_write(GPIO_BRAKE_LIGHT_OUT_GROUP, GPIO_BRAKE_LIGHT_OUT_PIN, enable?SET:RESET);
#endif
}

u8  gpio_board_id(void) {
	return _board_id;
}

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

bool mc_get_gpio_brake1(void) {
#ifdef GPIO_BRAKE1_IN_GROUP
	return gpio_input_bit_get(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_bit_get(GPIO_MLOCK_IN_GROUP, GPIO_MLOCK_IN_PIN) == RESET;
#else
	return false;
#endif
}



void gpio_ir2136_enable(bool enable) {
#ifdef GD32_FOC_DEMO
	gpio_bit_write(_pins[IR2136S_Enable_pin].group, _pins[IR2136S_Enable_pin].pin, (enable)?SET:RESET);
#endif
}

void gpio_led1_enable(bool enable) {
#ifdef GD32_FOC_DEMO
	gpio_bit_write(_pins[LED1_Enable_pin].group, _pins[LED1_Enable_pin].pin, (enable)?SET:RESET);
#endif
}

void gpio_led2_enable(bool enable) {
#ifdef GD32_FOC_DEMO
	//gpio_bit_write(_pins[LED2_Enable_pin].group, _pins[LED2_Enable_pin].pin, (enable)?SET:RESET);
#endif
}

void gpio_led3_enable(bool enable) {
#ifdef GD32_FOC_DEMO
	gpio_bit_write(_pins[LED3_Enable_pin].group, _pins[LED3_Enable_pin].pin, (enable)?SET:RESET);
#endif
}

int gpio_startkey_value(void) {
#ifdef GD32_FOC_DEMO
	return gpio_input_bit_get(_pins[KEY_Start_pin].group, _pins[KEY_Start_pin].pin)==SET?1:0;
#else
	return 1;
#endif
}

int gpio_stopkey_value(void) {
#ifdef GD32_FOC_DEMO
	return gpio_input_bit_get(_pins[KEY_Stop_pin].group, _pins[KEY_Stop_pin].pin)==SET?1:0;
#else
	return 1;
#endif
}

int gpio_funckey_value(void) {
	return 0;
}


