wiegand_scan.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "../wiegand.h"
  2. FuriTimer* timer = NULL;
  3. static void wiegand_scan_isr_d0(void* context) {
  4. UNUSED(context);
  5. uint32_t time = DWT->CYCCNT;
  6. bool rise = furi_hal_gpio_read(pinD0);
  7. data[bit_count] = 0;
  8. if(rise) {
  9. data_rise[bit_count] = time;
  10. if(bit_count < MAX_BITS) {
  11. bit_count++;
  12. }
  13. } else {
  14. data_fall[bit_count] = time;
  15. }
  16. }
  17. static void wiegand_scan_isr_d1(void* context) {
  18. UNUSED(context);
  19. uint32_t time = DWT->CYCCNT;
  20. bool rise = furi_hal_gpio_read(pinD1);
  21. data[bit_count] = 1;
  22. if(rise) {
  23. data_rise[bit_count] = time;
  24. if(bit_count < MAX_BITS) {
  25. bit_count++;
  26. }
  27. } else {
  28. data_fall[bit_count] = time;
  29. }
  30. }
  31. static void wiegand_start_scan(void* context) {
  32. UNUSED(context);
  33. data_saved = false;
  34. bit_count = 0;
  35. furi_hal_gpio_init_simple(pinD0, GpioModeInterruptRiseFall);
  36. furi_hal_gpio_init_simple(pinD1, GpioModeInterruptRiseFall);
  37. furi_hal_gpio_add_int_callback(pinD0, wiegand_scan_isr_d0, NULL);
  38. furi_hal_gpio_add_int_callback(pinD1, wiegand_scan_isr_d1, NULL);
  39. furi_timer_start(timer, 100);
  40. }
  41. static void wiegand_stop_scan(void* context) {
  42. UNUSED(context);
  43. furi_hal_gpio_remove_int_callback(pinD0);
  44. furi_hal_gpio_remove_int_callback(pinD1);
  45. furi_hal_gpio_init_simple(pinD0, GpioModeAnalog);
  46. furi_hal_gpio_init_simple(pinD1, GpioModeAnalog);
  47. furi_timer_stop(timer);
  48. }
  49. static void wiegand_scan_found(void* context) {
  50. App* app = context;
  51. FuriHalRtcDateTime datetime;
  52. furi_hal_rtc_get_datetime(&datetime);
  53. snprintf(
  54. app->file_name,
  55. 50,
  56. "%02d_%02d_%02d_%02d_%02d_%02d",
  57. datetime.year,
  58. datetime.month,
  59. datetime.day,
  60. datetime.hour,
  61. datetime.minute,
  62. datetime.second);
  63. furi_hal_vibro_on(true);
  64. furi_delay_ms(50);
  65. furi_hal_vibro_on(false);
  66. furi_delay_ms(50);
  67. wiegand_save(app);
  68. furi_hal_vibro_on(true);
  69. furi_delay_ms(50);
  70. furi_hal_vibro_on(false);
  71. furi_delay_ms(1000);
  72. wiegand_start_scan(app);
  73. }
  74. static void wiegand_scan_timer_callback(void* context) {
  75. App* app = context;
  76. uint32_t duration = DWT->CYCCNT;
  77. const uint32_t one_millisecond = 64000;
  78. if(bit_count == 0) {
  79. return;
  80. }
  81. duration -= data_fall[bit_count - 1];
  82. bool found = false;
  83. FURI_CRITICAL_ENTER();
  84. if(duration > 25 * one_millisecond) {
  85. if(bit_count == 4 || bit_count == 8 || bit_count == 24 || bit_count == 26 ||
  86. bit_count == 32 || bit_count == 34 || bit_count == 35 || bit_count == 36 ||
  87. bit_count == 37 || bit_count == 40 || bit_count == 48) {
  88. wiegand_stop_scan(app);
  89. found = true;
  90. } else {
  91. // No data, clear
  92. bit_count = 0;
  93. }
  94. }
  95. FURI_CRITICAL_EXIT();
  96. if(found) {
  97. wiegand_scan_found(app);
  98. }
  99. }
  100. void wiegand_scan_scene_on_enter(void* context) {
  101. App* app = context;
  102. timer = furi_timer_alloc(wiegand_scan_timer_callback, FuriTimerTypePeriodic, app);
  103. widget_reset(app->widget);
  104. widget_add_string_element(app->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Scan Wiegand");
  105. widget_add_string_element(
  106. app->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, "Files saved automatically.");
  107. widget_add_string_element(
  108. app->widget, 0, 30, AlignLeft, AlignTop, FontSecondary, "Vibrates on detection.");
  109. widget_add_string_element(
  110. app->widget, 0, 45, AlignLeft, AlignTop, FontSecondary, "D0/Green/A4");
  111. widget_add_string_element(
  112. app->widget, 0, 53, AlignLeft, AlignTop, FontSecondary, "D1/White/A7");
  113. wiegand_start_scan(app);
  114. view_dispatcher_switch_to_view(app->view_dispatcher, WiegandWidgetView);
  115. }
  116. void wiegand_scan_scene_on_exit(void* context) {
  117. App* app = context;
  118. wiegand_stop_scan(app);
  119. furi_timer_free(timer);
  120. }