mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-07 19:01:54 -07:00
Merge branch 'dev' into starline_ignore
This commit is contained in:
+38
-63
@@ -10,35 +10,29 @@
|
||||
#define COLS 128
|
||||
#define ROWS 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool autoscale;
|
||||
uint16_t us_per_sample;
|
||||
size_t timings_cnt;
|
||||
uint32_t* timings;
|
||||
uint32_t timings_sum;
|
||||
FuriMutex* mutex;
|
||||
typedef struct {
|
||||
bool autoscale;
|
||||
uint16_t us_per_sample;
|
||||
size_t timings_cnt;
|
||||
uint32_t* timings;
|
||||
uint32_t timings_sum;
|
||||
FuriMutex* mutex;
|
||||
} IRScopeState;
|
||||
|
||||
static void state_set_autoscale(IRScopeState* state)
|
||||
{
|
||||
if (state->autoscale)
|
||||
state->us_per_sample = state->timings_sum / (ROWS * COLS);
|
||||
static void state_set_autoscale(IRScopeState* state) {
|
||||
if(state->autoscale) state->us_per_sample = state->timings_sum / (ROWS * COLS);
|
||||
}
|
||||
|
||||
static void canvas_draw_str_outline(Canvas* canvas, int x, int y, const char* str)
|
||||
{
|
||||
static void canvas_draw_str_outline(Canvas* canvas, int x, int y, const char* str) {
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
for (int y1 = -1; y1 <= 1; ++y1)
|
||||
for (int x1 = -1; x1 <= 1; ++x1)
|
||||
canvas_draw_str(canvas, x + x1, y + y1, str);
|
||||
for(int y1 = -1; y1 <= 1; ++y1)
|
||||
for(int x1 = -1; x1 <= 1; ++x1) canvas_draw_str(canvas, x + x1, y + y1, str);
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str(canvas, x, y, str);
|
||||
}
|
||||
|
||||
static void render_callback(Canvas* canvas, void* ctx)
|
||||
{
|
||||
static void render_callback(Canvas* canvas, void* ctx) {
|
||||
const IRScopeState* state = (IRScopeState*)ctx;
|
||||
|
||||
furi_mutex_acquire(state->mutex, FuriWaitForever);
|
||||
@@ -51,19 +45,16 @@ static void render_callback(Canvas* canvas, void* ctx)
|
||||
bool done = false;
|
||||
size_t ix = 0;
|
||||
int timing_cols = -1; // Count of columns used to draw the current timing
|
||||
for (size_t row = 0; row < ROWS && !done; ++row)
|
||||
{
|
||||
for (size_t col = 0; col < COLS && !done; ++col)
|
||||
{
|
||||
for(size_t row = 0; row < ROWS && !done; ++row) {
|
||||
for(size_t col = 0; col < COLS && !done; ++col) {
|
||||
done = ix >= state->timings_cnt;
|
||||
|
||||
if (!done && timing_cols < 0)
|
||||
{
|
||||
if(!done && timing_cols < 0) {
|
||||
timing_cols = state->timings[ix] / state->us_per_sample;
|
||||
on = !on;
|
||||
}
|
||||
|
||||
if (timing_cols == 0) ++ix;
|
||||
if(timing_cols == 0) ++ix;
|
||||
|
||||
int y = row * 8 + 7;
|
||||
canvas_draw_line(canvas, col, y, col, y - (on ? 5 : 0));
|
||||
@@ -72,10 +63,9 @@ static void render_callback(Canvas* canvas, void* ctx)
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
if (state->autoscale)
|
||||
if(state->autoscale)
|
||||
canvas_draw_str_outline(canvas, 100, 64, "Auto");
|
||||
else
|
||||
{
|
||||
else {
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "%uus", state->us_per_sample);
|
||||
canvas_draw_str_outline(canvas, 100, 64, buf);
|
||||
@@ -84,14 +74,12 @@ static void render_callback(Canvas* canvas, void* ctx)
|
||||
furi_mutex_release(state->mutex);
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, void* ctx)
|
||||
{
|
||||
static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
FuriMessageQueue* event_queue = ctx;
|
||||
furi_message_queue_put(event_queue, input_event, FuriWaitForever);
|
||||
}
|
||||
|
||||
static void ir_received_callback(void* ctx, InfraredWorkerSignal* signal)
|
||||
{
|
||||
static void ir_received_callback(void* ctx, InfraredWorkerSignal* signal) {
|
||||
furi_check(signal);
|
||||
IRScopeState* state = (IRScopeState*)ctx;
|
||||
|
||||
@@ -100,8 +88,7 @@ static void ir_received_callback(void* ctx, InfraredWorkerSignal* signal)
|
||||
const uint32_t* timings;
|
||||
infrared_worker_get_raw_signal(signal, &timings, &state->timings_cnt);
|
||||
|
||||
if (state->timings)
|
||||
{
|
||||
if(state->timings) {
|
||||
free(state->timings);
|
||||
state->timings_sum = 0;
|
||||
}
|
||||
@@ -109,8 +96,7 @@ static void ir_received_callback(void* ctx, InfraredWorkerSignal* signal)
|
||||
state->timings = malloc(state->timings_cnt * sizeof(uint32_t));
|
||||
|
||||
// Copy and sum.
|
||||
for (size_t i = 0; i < state->timings_cnt; ++i)
|
||||
{
|
||||
for(size_t i = 0; i < state->timings_cnt; ++i) {
|
||||
state->timings[i] = timings[i];
|
||||
state->timings_sum += timings[i];
|
||||
}
|
||||
@@ -120,24 +106,21 @@ static void ir_received_callback(void* ctx, InfraredWorkerSignal* signal)
|
||||
furi_mutex_release(state->mutex);
|
||||
}
|
||||
|
||||
int32_t ir_scope_app(void* p)
|
||||
{
|
||||
int32_t ir_scope_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
||||
furi_check(event_queue);
|
||||
|
||||
if(furi_hal_infrared_is_busy())
|
||||
{
|
||||
if(furi_hal_infrared_is_busy()) {
|
||||
FURI_LOG_E(TAG, "Infrared is busy.");
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
IRScopeState state = { .autoscale = false, .us_per_sample = 200,
|
||||
.timings = NULL, .timings_cnt = 0, .mutex = NULL };
|
||||
IRScopeState state = {
|
||||
.autoscale = false, .us_per_sample = 200, .timings = NULL, .timings_cnt = 0, .mutex = NULL};
|
||||
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
if(!state.mutex)
|
||||
{
|
||||
if(!state.mutex) {
|
||||
FURI_LOG_E(TAG, "Cannot create mutex.");
|
||||
return -1;
|
||||
}
|
||||
@@ -157,30 +140,22 @@ int32_t ir_scope_app(void* p)
|
||||
|
||||
InputEvent event;
|
||||
bool processing = true;
|
||||
while(processing && furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk)
|
||||
{
|
||||
if (event.type == InputTypeRelease)
|
||||
{
|
||||
while(processing &&
|
||||
furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
|
||||
if(event.type == InputTypeRelease) {
|
||||
furi_mutex_acquire(state.mutex, FuriWaitForever);
|
||||
|
||||
if (event.key == InputKeyBack)
|
||||
{
|
||||
if(event.key == InputKeyBack) {
|
||||
processing = false;
|
||||
}
|
||||
else if (event.key == InputKeyUp)
|
||||
{
|
||||
} else if(event.key == InputKeyUp) {
|
||||
state.us_per_sample = MIN(1000, state.us_per_sample + 25);
|
||||
state.autoscale = false;
|
||||
}
|
||||
else if (event.key == InputKeyDown)
|
||||
{
|
||||
} else if(event.key == InputKeyDown) {
|
||||
state.us_per_sample = MAX(25, state.us_per_sample - 25);
|
||||
state.autoscale = false;
|
||||
}
|
||||
else if (event.key == InputKeyOk)
|
||||
{
|
||||
} else if(event.key == InputKeyOk) {
|
||||
state.autoscale = !state.autoscale;
|
||||
if (state.autoscale)
|
||||
if(state.autoscale)
|
||||
state_set_autoscale(&state);
|
||||
else
|
||||
state.us_per_sample = 200;
|
||||
@@ -195,7 +170,7 @@ int32_t ir_scope_app(void* p)
|
||||
infrared_worker_rx_stop(worker);
|
||||
infrared_worker_free(worker);
|
||||
|
||||
if (state.timings) free(state.timings);
|
||||
if(state.timings) free(state.timings);
|
||||
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
|
||||
+7
-2
@@ -1,5 +1,9 @@
|
||||
# UART Terminal for Flipper Zero
|
||||
# UART Terminal for Flipper Zero
|
||||
[Flipper Zero](https://flipperzero.one/) app to control various devices via UART interface.
|
||||
## Download fap
|
||||
| **FW Official** | **FW Unleashed** |
|
||||
| - | - |
|
||||
| [](https://flipc.org/cool4uma/UART_Terminal) | [](https://flipc.org/cool4uma/UART_Terminal?firmware=unleashed) |
|
||||
|
||||
## Capabilities
|
||||
- Read log and command output by uart
|
||||
@@ -29,6 +33,7 @@ Copy the contents of the repository to the applications_user/uart_terminal folde
|
||||
|
||||
Or use the tool [uFBT](https://github.com/flipperdevices/flipperzero-ufbt) for building applications for Flipper Zero.
|
||||
|
||||
|
||||
## How it works
|
||||
|
||||
|
||||
@@ -42,4 +47,4 @@ Or use the tool [uFBT](https://github.com/flipperdevices/flipperzero-ufbt) for b
|
||||
|
||||
## INFO:
|
||||
|
||||
~70% of the source code is taken from the [Wifi Marauder](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) project. Many thanks to the developers of the Wifi Marauder project.
|
||||
~60% of the source code is taken from the [Wifi Marauder](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) project. Many thanks to the developers of the Wifi Marauder project.
|
||||
|
||||
+15
-5
@@ -111,11 +111,21 @@ void uart_terminal_scene_console_output_on_enter(void* context) {
|
||||
uart_terminal_uart_set_handle_rx_data_cb(
|
||||
app->uart, uart_terminal_console_output_handle_rx_data_cb); // setup callback for rx thread
|
||||
|
||||
// Send command with newline '\n'
|
||||
// Send command with CR+LF or newline '\n'
|
||||
if(app->is_command && app->selected_tx_string) {
|
||||
uart_terminal_uart_tx(
|
||||
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
|
||||
uart_terminal_uart_tx((uint8_t*)("\n"), 1);
|
||||
if(app->TERMINAL_MODE == 1) {
|
||||
// char buffer[240];
|
||||
// snprintf(buffer, 240, "%s\r\n", (app->selected_tx_string));
|
||||
// uart_terminal_uart_tx((unsigned char *)buffer, strlen(buffer));
|
||||
uart_terminal_uart_tx(
|
||||
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
|
||||
uart_terminal_uart_tx((uint8_t*)("\r"), 1);
|
||||
uart_terminal_uart_tx((uint8_t*)("\n"), 1);
|
||||
} else {
|
||||
uart_terminal_uart_tx(
|
||||
(uint8_t*)(app->selected_tx_string), strlen(app->selected_tx_string));
|
||||
uart_terminal_uart_tx((uint8_t*)("\n"), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,4 +154,4 @@ void uart_terminal_scene_console_output_on_exit(void* context) {
|
||||
//if(app->is_command) {
|
||||
// uart_terminal_uart_tx((uint8_t*)("exit\n"), strlen("exit\n"));
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ const UART_TerminalItem items[NUM_MENU_ITEMS] = {
|
||||
FOCUS_CONSOLE_TOGGLE,
|
||||
NO_TIP},
|
||||
{"Send command", {""}, 1, {""}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||
{"Send AT command", {""}, 1, {"AT"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP},
|
||||
{"Fast cmd",
|
||||
{"help", "uptime", "date", "df -h", "ps", "dmesg", "reboot", "poweroff"},
|
||||
8,
|
||||
|
||||
+7
-1
@@ -25,7 +25,13 @@ void uart_terminal_scene_text_input_on_enter(void* context) {
|
||||
// Setup view
|
||||
UART_TextInput* text_input = app->text_input;
|
||||
// Add help message to header
|
||||
uart_text_input_set_header_text(text_input, "Send command to UART");
|
||||
if(0 == strncmp("AT", app->selected_tx_string, strlen("AT"))) {
|
||||
app->TERMINAL_MODE = 1;
|
||||
uart_text_input_set_header_text(text_input, "Send AT command to UART");
|
||||
} else {
|
||||
app->TERMINAL_MODE = 0;
|
||||
uart_text_input_set_header_text(text_input, "Send command to UART");
|
||||
}
|
||||
uart_text_input_set_result_callback(
|
||||
text_input,
|
||||
uart_terminal_scene_text_input_callback,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include "uart_text_input.h"
|
||||
|
||||
#define NUM_MENU_ITEMS (4)
|
||||
#define NUM_MENU_ITEMS (5)
|
||||
|
||||
#define UART_TERMINAL_TEXT_BOX_STORE_SIZE (4096)
|
||||
#define UART_TERMINAL_TEXT_INPUT_STORE_SIZE (512)
|
||||
@@ -40,6 +40,7 @@ struct UART_TerminalApp {
|
||||
bool focus_console_start;
|
||||
bool show_stopscan_tip;
|
||||
int BAUDRATE;
|
||||
int TERMINAL_MODE; //1=AT mode, 0=other mode
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
||||
+57
-11
@@ -1,6 +1,7 @@
|
||||
#include "uart_text_input.h"
|
||||
#include <gui/elements.h>
|
||||
#include "uart_terminal_icons.h"
|
||||
#include "uart_terminal_app_i.h"
|
||||
#include <furi.h>
|
||||
|
||||
struct UART_TextInput {
|
||||
@@ -36,6 +37,8 @@ static const uint8_t keyboard_origin_x = 1;
|
||||
static const uint8_t keyboard_origin_y = 29;
|
||||
static const uint8_t keyboard_row_count = 4;
|
||||
|
||||
#define mode_AT "Send AT command to UART"
|
||||
|
||||
#define ENTER_KEY '\r'
|
||||
#define BACKSPACE_KEY '\b'
|
||||
|
||||
@@ -163,6 +166,47 @@ static bool char_is_lowercase(char letter) {
|
||||
return (letter >= 0x61 && letter <= 0x7A);
|
||||
}
|
||||
|
||||
static bool char_is_uppercase(char letter) {
|
||||
return (letter >= 0x41 && letter <= 0x5A);
|
||||
}
|
||||
|
||||
static char char_to_lowercase(const char letter) {
|
||||
switch(letter) {
|
||||
case ' ':
|
||||
return 0x5f;
|
||||
break;
|
||||
case ')':
|
||||
return 0x28;
|
||||
break;
|
||||
case '}':
|
||||
return 0x7b;
|
||||
break;
|
||||
case ']':
|
||||
return 0x5b;
|
||||
break;
|
||||
case '\\':
|
||||
return 0x2f;
|
||||
break;
|
||||
case ':':
|
||||
return 0x3b;
|
||||
break;
|
||||
case ',':
|
||||
return 0x2e;
|
||||
break;
|
||||
case '?':
|
||||
return 0x21;
|
||||
break;
|
||||
case '>':
|
||||
return 0x3c;
|
||||
break;
|
||||
}
|
||||
if(char_is_uppercase(letter)) {
|
||||
return (letter + 0x20);
|
||||
} else {
|
||||
return letter;
|
||||
}
|
||||
}
|
||||
|
||||
static char char_to_uppercase(const char letter) {
|
||||
switch(letter) {
|
||||
case '_':
|
||||
@@ -193,7 +237,7 @@ static char char_to_uppercase(const char letter) {
|
||||
return 0x3e;
|
||||
break;
|
||||
}
|
||||
if(isalpha(letter)) {
|
||||
if(char_is_lowercase(letter)) {
|
||||
return (letter - 0x20);
|
||||
} else {
|
||||
return letter;
|
||||
@@ -209,7 +253,7 @@ static void uart_text_input_backspace_cb(UART_TextInputModel* model) {
|
||||
|
||||
static void uart_text_input_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
UART_TextInputModel* model = _model;
|
||||
uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
|
||||
//uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
|
||||
uint8_t needed_string_width = canvas_width(canvas) - 8;
|
||||
uint8_t start_pos = 4;
|
||||
|
||||
@@ -291,15 +335,12 @@ static void uart_text_input_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
|
||||
if(model->clear_default_text ||
|
||||
(text_length == 0 && char_is_lowercase(keys[column].text))) {
|
||||
if(0 == strcmp(model->header, mode_AT)) {
|
||||
canvas_draw_glyph(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
//char_to_uppercase(keys[column].text));
|
||||
keys[column].text);
|
||||
char_to_uppercase(keys[column].text));
|
||||
} else {
|
||||
canvas_draw_glyph(
|
||||
canvas,
|
||||
@@ -372,10 +413,18 @@ static void uart_text_input_handle_ok(
|
||||
char selected = get_selected_char(model);
|
||||
uint8_t text_length = strlen(model->text_buffer);
|
||||
|
||||
if(shift) {
|
||||
if(0 == strcmp(model->header, mode_AT)) {
|
||||
selected = char_to_uppercase(selected);
|
||||
}
|
||||
|
||||
if(shift) {
|
||||
if(0 == strcmp(model->header, mode_AT)) {
|
||||
selected = char_to_lowercase(selected);
|
||||
} else {
|
||||
selected = char_to_uppercase(selected);
|
||||
}
|
||||
}
|
||||
|
||||
if(selected == ENTER_KEY) {
|
||||
if(model->validator_callback &&
|
||||
(!model->validator_callback(
|
||||
@@ -392,9 +441,6 @@ static void uart_text_input_handle_ok(
|
||||
text_length = 0;
|
||||
}
|
||||
if(text_length < (model->text_buffer_size - 1)) {
|
||||
if(text_length == 0 && char_is_lowercase(selected)) {
|
||||
//selected = char_to_uppercase(selected);
|
||||
}
|
||||
model->text_buffer[text_length] = selected;
|
||||
model->text_buffer[text_length + 1] = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user