diff options
Diffstat (limited to 'firmware/targets/f7/furi_hal/furi_hal_gpio.c')
-rw-r--r-- | firmware/targets/f7/furi_hal/furi_hal_gpio.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/firmware/targets/f7/furi_hal/furi_hal_gpio.c b/firmware/targets/f7/furi_hal/furi_hal_gpio.c new file mode 100644 index 00000000..8c2aefe2 --- /dev/null +++ b/firmware/targets/f7/furi_hal/furi_hal_gpio.c @@ -0,0 +1,299 @@ +#include <furi.h> +#include <furi_hal_gpio.h> +#include <furi_hal_version.h> + +#define GET_SYSCFG_EXTI_PORT(gpio) \ + (((gpio) == (GPIOA)) ? LL_SYSCFG_EXTI_PORTA : \ + ((gpio) == (GPIOB)) ? LL_SYSCFG_EXTI_PORTB : \ + ((gpio) == (GPIOC)) ? LL_SYSCFG_EXTI_PORTC : \ + ((gpio) == (GPIOD)) ? LL_SYSCFG_EXTI_PORTD : \ + ((gpio) == (GPIOE)) ? LL_SYSCFG_EXTI_PORTE : \ + LL_SYSCFG_EXTI_PORTH) + +#define GPIO_PIN_MAP(pin, prefix) \ + (((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \ + ((pin) == (LL_GPIO_PIN_1)) ? prefix##1 : \ + ((pin) == (LL_GPIO_PIN_2)) ? prefix##2 : \ + ((pin) == (LL_GPIO_PIN_3)) ? prefix##3 : \ + ((pin) == (LL_GPIO_PIN_4)) ? prefix##4 : \ + ((pin) == (LL_GPIO_PIN_5)) ? prefix##5 : \ + ((pin) == (LL_GPIO_PIN_6)) ? prefix##6 : \ + ((pin) == (LL_GPIO_PIN_7)) ? prefix##7 : \ + ((pin) == (LL_GPIO_PIN_8)) ? prefix##8 : \ + ((pin) == (LL_GPIO_PIN_9)) ? prefix##9 : \ + ((pin) == (LL_GPIO_PIN_10)) ? prefix##10 : \ + ((pin) == (LL_GPIO_PIN_11)) ? prefix##11 : \ + ((pin) == (LL_GPIO_PIN_12)) ? prefix##12 : \ + ((pin) == (LL_GPIO_PIN_13)) ? prefix##13 : \ + ((pin) == (LL_GPIO_PIN_14)) ? prefix##14 : \ + prefix##15) + +#define GET_SYSCFG_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_SYSCFG_EXTI_LINE) +#define GET_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_EXTI_LINE_) + +static volatile GpioInterrupt gpio_interrupt[GPIO_NUMBER]; + +static uint8_t hal_gpio_get_pin_num(const GpioPin* gpio) { + uint8_t pin_num = 0; + for(pin_num = 0; pin_num < GPIO_NUMBER; pin_num++) { + if(gpio->pin & (1 << pin_num)) break; + } + return pin_num; +} + +void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode) { + hal_gpio_init(gpio, mode, GpioPullNo, GpioSpeedLow); +} + +void hal_gpio_init( + const GpioPin* gpio, + const GpioMode mode, + const GpioPull pull, + const GpioSpeed speed) { + // we cannot set alternate mode in this function + furi_assert(mode != GpioModeAltFunctionPushPull); + furi_assert(mode != GpioModeAltFunctionOpenDrain); + + hal_gpio_init_ex(gpio, mode, pull, speed, GpioAltFnUnused); +} + +void hal_gpio_init_ex( + const GpioPin* gpio, + const GpioMode mode, + const GpioPull pull, + const GpioSpeed speed, + const GpioAltFn alt_fn) { + uint32_t sys_exti_port = GET_SYSCFG_EXTI_PORT(gpio->port); + uint32_t sys_exti_line = GET_SYSCFG_EXTI_LINE(gpio->pin); + uint32_t exti_line = GET_EXTI_LINE(gpio->pin); + + // Configure gpio with interrupts disabled + __disable_irq(); + // Set gpio speed + if(speed == GpioSpeedLow) { + LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_LOW); + } else if(speed == GpioSpeedMedium) { + LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_MEDIUM); + } else if(speed == GpioSpeedHigh) { + LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_HIGH); + } else { + LL_GPIO_SetPinSpeed(gpio->port, gpio->pin, LL_GPIO_SPEED_FREQ_VERY_HIGH); + } + // Set gpio pull mode + if(pull == GpioPullNo) { + LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_NO); + } else if(pull == GpioPullUp) { + LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_UP); + } else { + LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_DOWN); + } + // Set gpio mode + if(mode >= GpioModeInterruptRise) { + // Set pin in interrupt mode + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT); + LL_SYSCFG_SetEXTISource(sys_exti_port, sys_exti_line); + if(mode == GpioModeInterruptRise || mode == GpioModeInterruptRiseFall) { + LL_EXTI_EnableIT_0_31(exti_line); + LL_EXTI_EnableRisingTrig_0_31(exti_line); + } + if(mode == GpioModeInterruptFall || mode == GpioModeInterruptRiseFall) { + LL_EXTI_EnableIT_0_31(exti_line); + LL_EXTI_EnableFallingTrig_0_31(exti_line); + } + if(mode == GpioModeEventRise || mode == GpioModeInterruptRiseFall) { + LL_EXTI_EnableEvent_0_31(exti_line); + LL_EXTI_EnableRisingTrig_0_31(exti_line); + } + if(mode == GpioModeEventFall || mode == GpioModeInterruptRiseFall) { + LL_EXTI_EnableEvent_0_31(exti_line); + LL_EXTI_EnableFallingTrig_0_31(exti_line); + } + } else { + // Disable interrupt if it was set + if(LL_SYSCFG_GetEXTISource(sys_exti_line) == sys_exti_port && + LL_EXTI_IsEnabledIT_0_31(exti_line)) { + LL_EXTI_DisableIT_0_31(exti_line); + LL_EXTI_DisableRisingTrig_0_31(exti_line); + LL_EXTI_DisableFallingTrig_0_31(exti_line); + } + // Set not interrupt pin modes + if(mode == GpioModeInput) { + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_INPUT); + } else if(mode == GpioModeOutputPushPull || mode == GpioModeAltFunctionPushPull) { + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_PUSHPULL); + } else if(mode == GpioModeOutputOpenDrain || mode == GpioModeAltFunctionOpenDrain) { + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_OUTPUT); + LL_GPIO_SetPinOutputType(gpio->port, gpio->pin, LL_GPIO_OUTPUT_OPENDRAIN); + } else if(mode == GpioModeAnalog) { + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG); + } + } + + if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { + // enable alternate mode + LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ALTERNATE); + + // set alternate function + if(hal_gpio_get_pin_num(gpio) < 8) { + LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); + } else { + LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); + } + } + + __enable_irq(); +} + +void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx) { + furi_assert(gpio); + furi_assert(cb); + + __disable_irq(); + uint8_t pin_num = hal_gpio_get_pin_num(gpio); + furi_assert(gpio_interrupt[pin_num].callback == NULL); + gpio_interrupt[pin_num].callback = cb; + gpio_interrupt[pin_num].context = ctx; + gpio_interrupt[pin_num].ready = true; + __enable_irq(); +} + +void hal_gpio_enable_int_callback(const GpioPin* gpio) { + furi_assert(gpio); + + __disable_irq(); + uint8_t pin_num = hal_gpio_get_pin_num(gpio); + if(gpio_interrupt[pin_num].callback) { + gpio_interrupt[pin_num].ready = true; + } + __enable_irq(); +} + +void hal_gpio_disable_int_callback(const GpioPin* gpio) { + furi_assert(gpio); + + __disable_irq(); + uint8_t pin_num = hal_gpio_get_pin_num(gpio); + gpio_interrupt[pin_num].ready = false; + __enable_irq(); +} + +void hal_gpio_remove_int_callback(const GpioPin* gpio) { + furi_assert(gpio); + + __disable_irq(); + uint8_t pin_num = hal_gpio_get_pin_num(gpio); + gpio_interrupt[pin_num].callback = NULL; + gpio_interrupt[pin_num].context = NULL; + gpio_interrupt[pin_num].ready = false; + __enable_irq(); +} + +static void hal_gpio_int_call(uint16_t pin_num) { + if(gpio_interrupt[pin_num].callback && gpio_interrupt[pin_num].ready) { + gpio_interrupt[pin_num].callback(gpio_interrupt[pin_num].context); + } +} + +/* Interrupt handlers */ +void EXTI0_IRQHandler(void) { + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_0)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0); + hal_gpio_int_call(0); + } +} + +void EXTI1_IRQHandler(void) { + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_1)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_1); + hal_gpio_int_call(1); + } +} + +void EXTI2_IRQHandler(void) { + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_2)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2); + hal_gpio_int_call(2); + } +} + +void EXTI3_IRQHandler(void) { + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_3)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_3); + hal_gpio_int_call(3); + } +} + +void EXTI4_IRQHandler(void) { + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_4)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_4); + hal_gpio_int_call(4); + } +} + +void EXTI9_5_IRQHandler(void) { + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_5)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5); + hal_gpio_int_call(5); + } + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_6)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6); + hal_gpio_int_call(6); + } + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_7)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_7); + hal_gpio_int_call(7); + } + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_8)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_8); + hal_gpio_int_call(8); + } + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_9)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9); + hal_gpio_int_call(9); + } +} + +void EXTI15_10_IRQHandler(void) { + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_10)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_10); + hal_gpio_int_call(10); + } + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_11)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_11); + hal_gpio_int_call(11); + } + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_12)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_12); + hal_gpio_int_call(12); + } + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_13)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_13); + hal_gpio_int_call(13); + } + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_14)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_14); + hal_gpio_int_call(14); + } + if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_15)) { + LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_15); + hal_gpio_int_call(15); + } +} + +extern COMP_HandleTypeDef hcomp1; + +bool hal_gpio_get_rfid_in_level() { + bool value = false; + if(furi_hal_version_get_hw_version() > 7) { + value = (HAL_COMP_GetOutputLevel(&hcomp1) == COMP_OUTPUT_LEVEL_LOW); + } else { + value = (HAL_COMP_GetOutputLevel(&hcomp1) == COMP_OUTPUT_LEVEL_HIGH); + } + +#ifdef INVERT_RFID_IN + return !value; +#else + return value; +#endif +} |