Skip to content

Commit bdb10b6

Browse files
authored
Merge pull request #32 from rnadyrshin/hex-mode
Hex mode in UART Terminal
2 parents 0916cc1 + 2212ab0 commit bdb10b6

16 files changed

+1090
-246
lines changed

base_pack/uart_terminal/README.md

+18-9
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,20 @@
66
| [![FAP Factory](https://flipc.org/api/v1/cool4uma/UART_Terminal/badge)](https://flipc.org/cool4uma/UART_Terminal) | [![FAP Factory](https://flipc.org/api/v1/cool4uma/UART_Terminal/badge?firmware=unleashed)](https://flipc.org/cool4uma/UART_Terminal?firmware=unleashed) |
77

88
## Capabilities
9-
- Read log and command output by uart
10-
- Send commands by uart
11-
- Set baud rate
12-
- Fast commands
9+
- Reading from UART in text or hex mode
10+
- Sending commands
11+
- Sending AT commands
12+
- Sending fast commands
13+
- Sending binary packets (in hex)
14+
- Baudrate selection
15+
- UART pins selection (2 options)
1316

1417
## Connecting
15-
| Flipper Zero pin | UART interface |
16-
| ---------------- | --------------- |
17-
| 13 TX | RX |
18-
| 14 RX | TX |
19-
|8, 18 GND | GND |
18+
| Device UART interface | Flipper Zero pin (default) | Flipper Zero pin (option) |
19+
| :----------------: | :---------------: | :---------------: |
20+
| RX | 13 TX | 15 TX |
21+
| TX | 14 RX | 16 TX |
22+
| GND | 8, 18 GND | 8, 18 GND |
2023

2124
Info: If possible, do not power your devices from 3V3 (pin 9) Flipper Zero. It does not support hot plugging.
2225

@@ -27,6 +30,12 @@ To accommodate more characters on a small display, some characters are called up
2730

2831
![kbf](https://user-images.githubusercontent.com/122148894/212286637-7063f1ee-c6ff-46b9-8dc5-79a5f367fab1.png)
2932

33+
## Hex mode
34+
Hexadecimal mode is useful for working with simple binary protocols.
35+
You can see the bytes being received in hexadecimal in the terminal window.
36+
You can also send binary packets to UART. A simplified keyboard is used to enter packet bytes.
37+
38+
![004](https://github.com/rnadyrshin/UART_Terminal/assets/110516632/d5d3c09b-accc-4e6f-b777-81e751284108)
3039

3140
## How to install
3241
Copy the contents of the repository to the applications_user/uart_terminal folder Flipper Zero firmware and build app with the command ./fbt fap_uart_terminal.

base_pack/uart_terminal/application.fam

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ App(
1010
fap_category="GPIO",
1111
fap_icon_assets="assets",
1212
fap_author="@cool4uma & (some fixes by @xMasterX)",
13-
fap_version="1.2",
13+
fap_version="1.3",
1414
fap_description="Control various devices via the Flipper Zero UART interface.",
1515
)

base_pack/uart_terminal/scenes/uart_terminal_scene.h

+6
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,9 @@ extern const SceneManagerHandlers uart_terminal_scene_handlers;
2727
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
2828
#include "uart_terminal_scene_config.h"
2929
#undef ADD_SCENE
30+
31+
#define UART_PINS_ITEM_IDX (0)
32+
#define BAUDRATE_ITEM_IDX (1)
33+
#define HEX_MODE_ITEM_IDX (2)
34+
35+
#define DEFAULT_BAUDRATE_OPT_IDX (18)
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
ADD_SCENE(uart_terminal, start, Start)
2+
ADD_SCENE(uart_terminal, setup, Setup)
23
ADD_SCENE(uart_terminal, console_output, ConsoleOutput)
34
ADD_SCENE(uart_terminal, text_input, UART_TextInput)
5+
ADD_SCENE(uart_terminal, hex_input, UART_HexInput)
6+
ADD_SCENE(uart_terminal, help, Help)

base_pack/uart_terminal/scenes/uart_terminal_scene_console_output.c

+79-154
Original file line numberDiff line numberDiff line change
@@ -3,177 +3,77 @@
33
void uart_terminal_console_output_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
44
furi_assert(context);
55
UART_TerminalApp* app = context;
6+
FuriString* new_str = furi_string_alloc();
7+
8+
if(app->hex_mode) {
9+
while (len--) {
10+
uint8_t byte = *(buf++);
11+
if(byte == '\0') break;
12+
furi_string_cat_printf(new_str, "%02X ", byte);
13+
}
14+
}
15+
else {
16+
buf[len] = '\0';
17+
furi_string_cat_printf(new_str, "%s", buf);
18+
}
619

720
// If text box store gets too big, then truncate it
8-
app->text_box_store_strlen += len;
9-
if(app->text_box_store_strlen >= UART_TERMINAL_TEXT_BOX_STORE_SIZE - 1) {
21+
app->text_box_store_strlen += furi_string_size(new_str);;
22+
while(app->text_box_store_strlen >= UART_TERMINAL_TEXT_BOX_STORE_SIZE - 1) {
1023
furi_string_right(app->text_box_store, app->text_box_store_strlen / 2);
1124
app->text_box_store_strlen = furi_string_size(app->text_box_store) + len;
1225
}
1326

14-
// Null-terminate buf and append to text box store
15-
buf[len] = '\0';
16-
furi_string_cat_printf(app->text_box_store, "%s", buf);
27+
furi_string_cat(app->text_box_store, new_str);
28+
furi_string_free(new_str);
1729

1830
view_dispatcher_send_custom_event(
1931
app->view_dispatcher, UART_TerminalEventRefreshConsoleOutput);
2032
}
2133

34+
static uint8_t hex_char_to_byte(const char c) {
35+
if(c >= '0' && c <= '9') {
36+
return c-'0';
37+
}
38+
if(c >= 'A' && c <= 'F') {
39+
return c-'A'+10;
40+
}
41+
if (c >= 'a' && c <= 'f') {
42+
return c-'a'+10;
43+
}
44+
return 0;
45+
}
46+
2247
void uart_terminal_scene_console_output_on_enter(void* context) {
2348
UART_TerminalApp* app = context;
2449

2550
TextBox* text_box = app->text_box;
2651
text_box_reset(app->text_box);
2752
text_box_set_font(text_box, TextBoxFontText);
28-
if(app->focus_console_start) {
29-
text_box_set_focus(text_box, TextBoxFocusStart);
30-
} else {
31-
text_box_set_focus(text_box, TextBoxFocusEnd);
32-
}
53+
text_box_set_focus(text_box, TextBoxFocusEnd);
3354

34-
//Change baudrate ///////////////////////////////////////////////////////////////////////////
35-
if(0 == strncmp("75", app->selected_tx_string, strlen("75")) && app->BAUDRATE != 75) {
36-
uart_terminal_uart_free(app->uart);
37-
app->BAUDRATE = 75;
38-
app->uart = uart_terminal_uart_init(app);
39-
}
40-
if(0 == strncmp("110", app->selected_tx_string, strlen("110")) && app->BAUDRATE != 110) {
41-
uart_terminal_uart_free(app->uart);
42-
app->BAUDRATE = 110;
43-
app->uart = uart_terminal_uart_init(app);
44-
}
45-
if(0 == strncmp("150", app->selected_tx_string, strlen("150")) && app->BAUDRATE != 150) {
46-
uart_terminal_uart_free(app->uart);
47-
app->BAUDRATE = 150;
48-
app->uart = uart_terminal_uart_init(app);
49-
}
50-
if(0 == strncmp("300", app->selected_tx_string, strlen("300")) && app->BAUDRATE != 300) {
51-
uart_terminal_uart_free(app->uart);
52-
app->BAUDRATE = 300;
53-
app->uart = uart_terminal_uart_init(app);
54-
}
55-
if(0 == strncmp("600", app->selected_tx_string, strlen("600")) && app->BAUDRATE != 600) {
56-
uart_terminal_uart_free(app->uart);
57-
app->BAUDRATE = 600;
58-
app->uart = uart_terminal_uart_init(app);
59-
}
60-
if(0 == strncmp("1200", app->selected_tx_string, strlen("1200")) && app->BAUDRATE != 1200) {
61-
uart_terminal_uart_free(app->uart);
62-
app->BAUDRATE = 1200;
63-
app->uart = uart_terminal_uart_init(app);
64-
}
65-
if(0 == strncmp("1800", app->selected_tx_string, strlen("1800")) && app->BAUDRATE != 1800) {
66-
uart_terminal_uart_free(app->uart);
67-
app->BAUDRATE = 1800;
68-
app->uart = uart_terminal_uart_init(app);
69-
}
70-
if(0 == strncmp("2400", app->selected_tx_string, strlen("2400")) && app->BAUDRATE != 2400) {
71-
uart_terminal_uart_free(app->uart);
72-
app->BAUDRATE = 2400;
73-
app->uart = uart_terminal_uart_init(app);
74-
}
75-
if(0 == strncmp("4800", app->selected_tx_string, strlen("4800")) && app->BAUDRATE != 4800) {
76-
uart_terminal_uart_free(app->uart);
77-
app->BAUDRATE = 4800;
78-
app->uart = uart_terminal_uart_init(app);
79-
}
80-
if(0 == strncmp("7200", app->selected_tx_string, strlen("7200")) && app->BAUDRATE != 7200) {
81-
uart_terminal_uart_free(app->uart);
82-
app->BAUDRATE = 7200;
83-
app->uart = uart_terminal_uart_init(app);
84-
}
85-
if(0 == strncmp("9600", app->selected_tx_string, strlen("9600")) && app->BAUDRATE != 9600) {
86-
uart_terminal_uart_free(app->uart);
87-
app->BAUDRATE = 9600;
88-
app->uart = uart_terminal_uart_init(app);
89-
}
90-
if(0 == strncmp("14400", app->selected_tx_string, strlen("14400")) && app->BAUDRATE != 14400) {
91-
uart_terminal_uart_free(app->uart);
92-
app->BAUDRATE = 14400;
93-
app->uart = uart_terminal_uart_init(app);
94-
}
95-
if(0 == strncmp("19200", app->selected_tx_string, strlen("19200")) && app->BAUDRATE != 19200) {
96-
uart_terminal_uart_free(app->uart);
97-
app->BAUDRATE = 19200;
98-
app->uart = uart_terminal_uart_init(app);
99-
}
100-
if(0 == strncmp("38400", app->selected_tx_string, strlen("38400")) && app->BAUDRATE != 38400) {
101-
uart_terminal_uart_free(app->uart);
102-
app->BAUDRATE = 38400;
103-
app->uart = uart_terminal_uart_init(app);
104-
}
105-
if(0 == strncmp("56000", app->selected_tx_string, strlen("56000")) && app->BAUDRATE != 56000) {
106-
uart_terminal_uart_free(app->uart);
107-
app->BAUDRATE = 56000;
108-
app->uart = uart_terminal_uart_init(app);
109-
}
110-
if(0 == strncmp("57600", app->selected_tx_string, strlen("57600")) && app->BAUDRATE != 57600) {
111-
uart_terminal_uart_free(app->uart);
112-
app->BAUDRATE = 57600;
113-
app->uart = uart_terminal_uart_init(app);
114-
}
115-
if(0 == strncmp("76800", app->selected_tx_string, strlen("76800")) && app->BAUDRATE != 76800) {
116-
uart_terminal_uart_free(app->uart);
117-
app->BAUDRATE = 76800;
118-
app->uart = uart_terminal_uart_init(app);
119-
}
120-
if(0 == strncmp("115200", app->selected_tx_string, strlen("115200")) &&
121-
app->BAUDRATE != 115200) {
122-
uart_terminal_uart_free(app->uart);
123-
app->BAUDRATE = 115200;
124-
app->uart = uart_terminal_uart_init(app);
125-
}
126-
if(0 == strncmp("128000", app->selected_tx_string, strlen("128000")) && app->BAUDRATE != 128000) {
127-
uart_terminal_uart_free(app->uart);
128-
app->BAUDRATE = 128000;
129-
app->uart = uart_terminal_uart_init(app);
130-
}
131-
if(0 == strncmp("230400", app->selected_tx_string, strlen("230400")) &&
132-
app->BAUDRATE != 230400) {
133-
uart_terminal_uart_free(app->uart);
134-
app->BAUDRATE = 230400;
135-
app->uart = uart_terminal_uart_init(app);
136-
}
137-
if(0 == strncmp("250000", app->selected_tx_string, strlen("250000")) && app->BAUDRATE != 250000) {
138-
uart_terminal_uart_free(app->uart);
139-
app->BAUDRATE = 250000;
140-
app->uart = uart_terminal_uart_init(app);
141-
}
142-
if(0 == strncmp("256000", app->selected_tx_string, strlen("256000")) && app->BAUDRATE != 256000) {
143-
uart_terminal_uart_free(app->uart);
144-
app->BAUDRATE = 256000;
145-
app->uart = uart_terminal_uart_init(app);
55+
bool need_reinit = false;
56+
57+
//Change baudrate
58+
if(app->BAUDRATE != app->NEW_BAUDRATE && app->NEW_BAUDRATE) {
59+
need_reinit = true;
14660
}
147-
if(0 == strncmp("460800", app->selected_tx_string, strlen("460800")) &&
148-
app->BAUDRATE != 460800) {
149-
uart_terminal_uart_free(app->uart);
150-
app->BAUDRATE = 460800;
151-
app->uart = uart_terminal_uart_init(app);
61+
62+
//Change UART port
63+
if(app->uart_ch != app->new_uart_ch) {
64+
need_reinit = true;
15265
}
153-
if(0 == strncmp("921600", app->selected_tx_string, strlen("921600")) &&
154-
app->BAUDRATE != 921600) {
66+
67+
if(need_reinit) {
15568
uart_terminal_uart_free(app->uart);
156-
app->BAUDRATE = 921600;
69+
app->BAUDRATE = app->NEW_BAUDRATE;
70+
app->uart_ch = app->new_uart_ch;
15771
app->uart = uart_terminal_uart_init(app);
15872
}
159-
/////////////////////////////////////////////////////////////////////////////////////////////////////
16073

16174
if(app->is_command) {
16275
furi_string_reset(app->text_box_store);
16376
app->text_box_store_strlen = 0;
164-
165-
if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) {
166-
const char* help_msg =
167-
"UART terminal for Flipper\n\nI'm in github: cool4uma\n\nThis app is a modified\nWiFi Marauder companion,\nThanks 0xchocolate(github)\nfor great code and app.\n\n";
168-
furi_string_cat_str(app->text_box_store, help_msg);
169-
app->text_box_store_strlen += strlen(help_msg);
170-
}
171-
172-
if(app->show_stopscan_tip) {
173-
const char* help_msg = "Press BACK to return\n";
174-
furi_string_cat_str(app->text_box_store, help_msg);
175-
app->text_box_store_strlen += strlen(help_msg);
176-
}
17777
}
17878

17979
// Set starting text - for "View Log", this will just be what was already in the text box store
@@ -186,16 +86,41 @@ void uart_terminal_scene_console_output_on_enter(void* context) {
18686
uart_terminal_uart_set_handle_rx_data_cb(
18787
app->uart, uart_terminal_console_output_handle_rx_data_cb); // setup callback for rx thread
18888

189-
// Send command with CR+LF or newline '\n'
190-
if(app->is_command && app->selected_tx_string) {
191-
if(app->TERMINAL_MODE == 1){
192-
uart_terminal_uart_tx(
193-
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
194-
uart_terminal_uart_tx((uint8_t*)("\r\n"), 2);
195-
} else {
196-
uart_terminal_uart_tx(
197-
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
198-
uart_terminal_uart_tx((uint8_t*)("\n"), 1);
89+
uint8_t uart_ch = app->uart_ch;
90+
91+
if(app->hex_mode) {
92+
// Send binary packet
93+
if(app->selected_tx_string) {
94+
const char *str = app->selected_tx_string;
95+
uint8_t digit_num = 0;
96+
uint8_t byte = 0;
97+
while (*str) {
98+
byte |= (hex_char_to_byte(*str) << ((1 - digit_num) * 4));
99+
100+
if(++digit_num == 2) {
101+
uart_terminal_uart_tx(uart_ch, &byte, 1);
102+
digit_num = 0;
103+
byte = 0;
104+
}
105+
str++;
106+
}
107+
108+
if(digit_num) {
109+
uart_terminal_uart_tx(uart_ch, &byte, 1);
110+
}
111+
}
112+
} else {
113+
// Send command with CR+LF or newline '\n'
114+
if(app->is_command && app->selected_tx_string) {
115+
if(app->TERMINAL_MODE == 1){
116+
uart_terminal_uart_tx(uart_ch,
117+
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
118+
uart_terminal_uart_tx(uart_ch, (uint8_t*)("\r\n"), 2);
119+
} else {
120+
uart_terminal_uart_tx(uart_ch,
121+
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
122+
uart_terminal_uart_tx(uart_ch, (uint8_t*)("\n"), 1);
123+
}
199124
}
200125
}
201126
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include "../uart_terminal_app_i.h"
2+
3+
void uart_terminal_scene_help_widget_callback(GuiButtonType result, InputType type, void* context) {
4+
UART_TerminalApp* app = context;
5+
if(type == InputTypeShort) {
6+
view_dispatcher_send_custom_event(app->view_dispatcher, result);
7+
}
8+
}
9+
10+
void uart_terminal_scene_help_on_enter(void* context) {
11+
UART_TerminalApp* app = context;
12+
13+
FuriString* temp_str;
14+
temp_str = furi_string_alloc();
15+
furi_string_printf(temp_str, "\nUART terminal for Flipper\n\nI'm in github: cool4uma\n\nThis app is a modified\nWiFi Marauder companion,\nThanks 0xchocolate(github)\nfor great code and app.\n\n");
16+
furi_string_cat_printf( temp_str, "Press BACK to return\n");
17+
18+
widget_add_text_box_element(
19+
app->widget,
20+
0,
21+
0,
22+
128,
23+
14,
24+
AlignCenter,
25+
AlignBottom,
26+
"\e#\e! \e!\n",
27+
false);
28+
widget_add_text_box_element(
29+
app->widget,
30+
0,
31+
2,
32+
128,
33+
14,
34+
AlignCenter,
35+
AlignBottom,
36+
"\e#\e! UART Terminal \e!\n",
37+
false);
38+
widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));
39+
furi_string_free(temp_str);
40+
41+
view_dispatcher_switch_to_view(app->view_dispatcher, UART_TerminalAppViewHelp);
42+
}
43+
44+
bool uart_terminal_scene_help_on_event(void* context, SceneManagerEvent event) {
45+
UART_TerminalApp* app = context;
46+
bool consumed = false;
47+
UNUSED(app);
48+
UNUSED(event);
49+
return consumed;
50+
}
51+
52+
void uart_terminal_scene_help_on_exit(void* context) {
53+
UART_TerminalApp* app = context;
54+
// Clear views
55+
widget_reset(app->widget);
56+
}

0 commit comments

Comments
 (0)