mag_scene_read.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Creator: Hummus@FlipperGang
  2. #include "../mag_i.h"
  3. #include "../helpers/mag_helpers.h"
  4. #include "mag_scene_read.h"
  5. #define TAG "MagSceneRead"
  6. void uart_callback(UartIrqEvent event, uint8_t data, void* context) {
  7. Mag* mag = context;
  8. if(event == UartIrqEventRXNE) {
  9. furi_stream_buffer_send(mag->uart_rx_stream, &data, 1, 0);
  10. furi_thread_flags_set(furi_thread_get_id(mag->uart_rx_thread), WorkerEvtRxDone);
  11. }
  12. }
  13. static int32_t uart_worker(void* context) {
  14. Mag* mag = context;
  15. mag->uart_rx_stream = furi_stream_buffer_alloc(UART_RX_BUF_SIZE, 1);
  16. mag->uart_text_box_store_strlen = 0;
  17. while(1) {
  18. uint32_t events =
  19. furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
  20. // furi_check((events & FuriFlagError) == 0);
  21. if(events & WorkerEvtStop) break;
  22. if(events & WorkerEvtRxDone) {
  23. FURI_LOG_D(TAG, "WorkerEvtRxDone");
  24. // notification_message(mag->notifications, &sequence_success);
  25. size_t len = furi_stream_buffer_receive(
  26. mag->uart_rx_stream, mag->uart_rx_buf, UART_RX_BUF_SIZE, 200);
  27. FURI_LOG_D(TAG, "UART RX len: %d", len);
  28. if(len > 0) {
  29. // If text box store gets too big, then truncate it
  30. mag->uart_text_box_store_strlen += len;
  31. if(mag->uart_text_box_store_strlen >= UART_TERMINAL_TEXT_BOX_STORE_SIZE - 1) {
  32. furi_string_right(
  33. mag->uart_text_box_store, mag->uart_text_box_store_strlen / 2);
  34. mag->uart_text_box_store_strlen =
  35. furi_string_size(mag->uart_text_box_store) + len;
  36. }
  37. // Add '\0' to the end of the string, and then add the new data
  38. mag->uart_rx_buf[len] = '\0';
  39. furi_string_cat_printf(mag->uart_text_box_store, "%s", mag->uart_rx_buf);
  40. FURI_LOG_D(TAG, "UART RX buf: %*.s", len, mag->uart_rx_buf);
  41. FURI_LOG_D(
  42. TAG, "UART RX store: %s", furi_string_get_cstr(mag->uart_text_box_store));
  43. }
  44. FURI_LOG_D(TAG, "UARTEventRxData");
  45. view_dispatcher_send_custom_event(mag->view_dispatcher, UARTEventRxData);
  46. }
  47. }
  48. furi_stream_buffer_free(mag->uart_rx_stream);
  49. return 0;
  50. }
  51. void update_widgets(Mag* mag) {
  52. // Clear widget from all elements
  53. widget_reset(mag->widget);
  54. // Titlebar
  55. widget_add_icon_element(mag->widget, 38, -1, &I_mag_file_10px);
  56. widget_add_string_element(mag->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "READ");
  57. widget_add_icon_element(mag->widget, 81, -1, &I_mag_file_10px);
  58. // Text box
  59. widget_add_text_scroll_element(
  60. mag->widget, 0, 10, 128, 40, furi_string_get_cstr(mag->uart_text_box_store));
  61. // Buttons
  62. widget_add_button_element(mag->widget, GuiButtonTypeLeft, "Clear", mag_widget_callback, mag);
  63. widget_add_button_element(mag->widget, GuiButtonTypeRight, "Parse", mag_widget_callback, mag);
  64. }
  65. void mag_scene_read_on_enter(void* context) {
  66. Mag* mag = context;
  67. FuriString* message = furi_string_alloc();
  68. furi_string_printf(message, "Please swipe a card!\n");
  69. mag->uart_text_box_store = message;
  70. view_dispatcher_switch_to_view(mag->view_dispatcher, MagViewWidget);
  71. update_widgets(mag);
  72. // Initialize UART
  73. // furi_hal_console_disable();
  74. furi_hal_uart_deinit(FuriHalUartIdUSART1);
  75. furi_hal_uart_init(FuriHalUartIdUSART1, 9600);
  76. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_callback, mag);
  77. FURI_LOG_D(TAG, "UART initialized");
  78. mag->uart_rx_thread = furi_thread_alloc();
  79. furi_thread_set_name(mag->uart_rx_thread, "UartRx");
  80. furi_thread_set_stack_size(mag->uart_rx_thread, 1024);
  81. furi_thread_set_context(mag->uart_rx_thread, mag);
  82. furi_thread_set_callback(mag->uart_rx_thread, uart_worker);
  83. furi_thread_start(mag->uart_rx_thread);
  84. FURI_LOG_D(TAG, "UART worker started");
  85. }
  86. bool mag_scene_read_on_event(void* context, SceneManagerEvent event) {
  87. Mag* mag = context;
  88. bool consumed = false;
  89. if(event.type == SceneManagerEventTypeCustom) {
  90. FURI_LOG_D(TAG, "Custom event: %ld", event.event);
  91. switch(event.event) {
  92. case GuiButtonTypeLeft: // Clear
  93. consumed = true;
  94. // Clear text box store
  95. furi_string_reset(mag->uart_text_box_store);
  96. mag->uart_text_box_store_strlen = 0;
  97. break;
  98. case GuiButtonTypeRight: // Parse
  99. consumed = true;
  100. FURI_LOG_D(TAG, "Trying to parse");
  101. MagDevice* mag_dev = mag->mag_dev;
  102. bool res = mag_device_parse_card_string(mag_dev, mag->uart_text_box_store);
  103. furi_string_reset(mag->uart_text_box_store);
  104. if(res) {
  105. notification_message(mag->notifications, &sequence_success);
  106. furi_string_printf(
  107. mag->uart_text_box_store,
  108. "Track 1: %.*s\nTrack 2: %.*s\nTrack 3: %.*s",
  109. mag_dev->dev_data.track[0].len,
  110. furi_string_get_cstr(mag_dev->dev_data.track[0].str),
  111. mag_dev->dev_data.track[1].len,
  112. furi_string_get_cstr(mag_dev->dev_data.track[1].str),
  113. mag_dev->dev_data.track[2].len,
  114. furi_string_get_cstr(mag_dev->dev_data.track[2].str));
  115. // Switch to saved menu scene
  116. scene_manager_next_scene(mag->scene_manager, MagSceneSavedMenu);
  117. } else {
  118. furi_string_printf(mag->uart_text_box_store, "Failed to parse! Try again\n");
  119. notification_message(mag->notifications, &sequence_error);
  120. }
  121. break;
  122. }
  123. update_widgets(mag);
  124. }
  125. return consumed;
  126. }
  127. void mag_scene_read_on_exit(void* context) {
  128. Mag* mag = context;
  129. // notification_message(mag->notifications, &sequence_blink_stop);
  130. widget_reset(mag->widget);
  131. // view_dispatcher_remove_view(mag->view_dispatcher, MagViewWidget);
  132. // Stop UART worker
  133. FURI_LOG_D(TAG, "Stopping UART worker");
  134. furi_thread_flags_set(furi_thread_get_id(mag->uart_rx_thread), WorkerEvtStop);
  135. furi_thread_join(mag->uart_rx_thread);
  136. furi_thread_free(mag->uart_rx_thread);
  137. FURI_LOG_D(TAG, "UART worker stopped");
  138. furi_string_free(mag->uart_text_box_store);
  139. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
  140. furi_hal_uart_deinit(FuriHalUartIdUSART1);
  141. // furi_hal_console_enable();
  142. notification_message(mag->notifications, &sequence_blink_stop);
  143. }