gpio.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #include "gpio.h"
  2. uint32_t last_switch = 0;
  3. uint32_t last_time_up_tick = 0;
  4. uint32_t last_time_down_tick = 0;
  5. static void gpio_interrupt_callback(void* context) {
  6. furi_assert(context);
  7. GPIOContext* gpio_context = context;
  8. uint32_t current_tick = furi_get_tick();
  9. if(last_switch > 0) {
  10. bool shift_up = furi_hal_gpio_read(gpio_context->pin) ^ gpio_context->inverted;
  11. if(shift_up) {
  12. last_time_down_tick = current_tick - last_switch;
  13. } else {
  14. last_time_up_tick = current_tick - last_switch;
  15. }
  16. GPIOEvent event = {
  17. .shift_up = shift_up,
  18. .time_passed_down = last_time_down_tick,
  19. .time_passed_up = last_time_up_tick};
  20. furi_message_queue_put(gpio_context->queue, &event, 0);
  21. }
  22. last_switch = current_tick;
  23. }
  24. static const GpioPin* data_pins_to_gpio_pins[] =
  25. {&gpio_ext_pa7, &gpio_ext_pa4, &gpio_ext_pb2, &gpio_ext_pc1, &gpio_ext_pc0};
  26. GPIOContext*
  27. gpio_start_listening(const LWCDataPin data_pin, bool inverted, void* callback_context) {
  28. GPIOContext* result = malloc(sizeof(GPIOContext));
  29. result->inverted = inverted;
  30. result->pin = data_pins_to_gpio_pins[data_pin];
  31. result->context = callback_context;
  32. result->queue = furi_message_queue_alloc(32, sizeof(GPIOEvent));
  33. furi_hal_gpio_add_int_callback(result->pin, gpio_interrupt_callback, result);
  34. furi_hal_gpio_enable_int_callback(result->pin);
  35. furi_hal_gpio_init(result->pin, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedVeryHigh);
  36. return result;
  37. }
  38. void gpio_stop_listening(GPIOContext* context) {
  39. furi_hal_gpio_disable_int_callback(context->pin);
  40. furi_hal_gpio_remove_int_callback(context->pin);
  41. furi_hal_gpio_init_simple(context->pin, GpioModeAnalog);
  42. }
  43. bool gpio_callback_with_event(GPIOContext* context, void (*callback)(GPIOEvent, void*)) {
  44. GPIOEvent event;
  45. FuriStatus event_status = furi_message_queue_get(context->queue, &event, 0);
  46. if(event_status == FuriStatusOk) {
  47. callback(event, context->context);
  48. return true;
  49. } else {
  50. return false;
  51. }
  52. }