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