Merge remote-tracking branch 'UFW/dev' into cc1101_ext

This commit is contained in:
gid9798
2023-07-03 11:15:32 +03:00
201 changed files with 4851 additions and 1904 deletions
+1
View File
@@ -12,5 +12,6 @@ App(
"display_test",
"text_box_test",
"file_browser_test",
"speaker_debug",
],
)
@@ -0,0 +1,10 @@
App(
appid="crash_test",
name="Crash Test",
apptype=FlipperAppType.DEBUG,
entry_point="crash_test_app",
cdefines=["APP_CRASH_TEST"],
requires=["gui"],
stack_size=1 * 1024,
fap_category="Debug",
)
+128
View File
@@ -0,0 +1,128 @@
#include <furi_hal.h>
#include <furi.h>
#include <gui/gui.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/submenu.h>
#define TAG "CrashTest"
typedef struct {
Gui* gui;
ViewDispatcher* view_dispatcher;
Submenu* submenu;
} CrashTest;
typedef enum {
CrashTestViewSubmenu,
} CrashTestView;
typedef enum {
CrashTestSubmenuCheck,
CrashTestSubmenuCheckMessage,
CrashTestSubmenuAssert,
CrashTestSubmenuAssertMessage,
CrashTestSubmenuCrash,
CrashTestSubmenuHalt,
} CrashTestSubmenu;
static void crash_test_submenu_callback(void* context, uint32_t index) {
CrashTest* instance = (CrashTest*)context;
UNUSED(instance);
switch(index) {
case CrashTestSubmenuCheck:
furi_check(false);
break;
case CrashTestSubmenuCheckMessage:
furi_check(false, "Crash test: furi_check with message");
break;
case CrashTestSubmenuAssert:
furi_assert(false);
break;
case CrashTestSubmenuAssertMessage:
furi_assert(false, "Crash test: furi_assert with message");
break;
case CrashTestSubmenuCrash:
furi_crash("Crash test: furi_crash");
break;
case CrashTestSubmenuHalt:
furi_halt("Crash test: furi_halt");
break;
default:
furi_crash("Programming error");
}
}
static uint32_t crash_test_exit_callback(void* context) {
UNUSED(context);
return VIEW_NONE;
}
CrashTest* crash_test_alloc() {
CrashTest* instance = malloc(sizeof(CrashTest));
View* view = NULL;
instance->gui = furi_record_open(RECORD_GUI);
instance->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(instance->view_dispatcher);
view_dispatcher_attach_to_gui(
instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen);
// Menu
instance->submenu = submenu_alloc();
view = submenu_get_view(instance->submenu);
view_set_previous_callback(view, crash_test_exit_callback);
view_dispatcher_add_view(instance->view_dispatcher, CrashTestViewSubmenu, view);
submenu_add_item(
instance->submenu, "Check", CrashTestSubmenuCheck, crash_test_submenu_callback, instance);
submenu_add_item(
instance->submenu,
"Check with message",
CrashTestSubmenuCheckMessage,
crash_test_submenu_callback,
instance);
submenu_add_item(
instance->submenu, "Assert", CrashTestSubmenuAssert, crash_test_submenu_callback, instance);
submenu_add_item(
instance->submenu,
"Assert with message",
CrashTestSubmenuAssertMessage,
crash_test_submenu_callback,
instance);
submenu_add_item(
instance->submenu, "Crash", CrashTestSubmenuCrash, crash_test_submenu_callback, instance);
submenu_add_item(
instance->submenu, "Halt", CrashTestSubmenuHalt, crash_test_submenu_callback, instance);
return instance;
}
void crash_test_free(CrashTest* instance) {
view_dispatcher_remove_view(instance->view_dispatcher, CrashTestViewSubmenu);
submenu_free(instance->submenu);
view_dispatcher_free(instance->view_dispatcher);
furi_record_close(RECORD_GUI);
free(instance);
}
int32_t crash_test_run(CrashTest* instance) {
view_dispatcher_switch_to_view(instance->view_dispatcher, CrashTestViewSubmenu);
view_dispatcher_run(instance->view_dispatcher);
return 0;
}
int32_t crash_test_app(void* p) {
UNUSED(p);
CrashTest* instance = crash_test_alloc();
int32_t ret = crash_test_run(instance);
crash_test_free(instance);
return ret;
}
@@ -6,6 +6,11 @@ static void comparator_trigger_callback(bool level, void* comp_ctx) {
furi_hal_gpio_write(&gpio_ext_pa7, !level);
}
void lfrfid_debug_view_tune_callback(void* context) {
LfRfidDebug* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, 0xBA);
}
void lfrfid_debug_scene_tune_on_enter(void* context) {
LfRfidDebug* app = context;
@@ -16,6 +21,8 @@ void lfrfid_debug_scene_tune_on_enter(void* context) {
furi_hal_rfid_tim_read_start(125000, 0.5);
lfrfid_debug_view_tune_set_callback(app->tune_view, lfrfid_debug_view_tune_callback, app);
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidDebugViewTune);
}
@@ -13,6 +13,8 @@ typedef struct {
uint32_t ARR;
uint32_t CCR;
int pos;
void (*update_callback)(void* context);
void* update_context;
} LfRfidTuneViewModel;
static void lfrfid_debug_view_tune_draw_callback(Canvas* canvas, void* _model) {
@@ -151,6 +153,18 @@ static bool lfrfid_debug_view_tune_input_callback(InputEvent* event, void* conte
consumed = false;
break;
}
if(event->key == InputKeyLeft || event->key == InputKeyRight) {
with_view_model(
tune_view->view,
LfRfidTuneViewModel * model,
{
if(model->update_callback) {
model->update_callback(model->update_context);
}
},
false);
}
}
return consumed;
@@ -161,19 +175,7 @@ LfRfidTuneView* lfrfid_debug_view_tune_alloc() {
tune_view->view = view_alloc();
view_set_context(tune_view->view, tune_view);
view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel));
with_view_model(
tune_view->view,
LfRfidTuneViewModel * model,
{
model->dirty = true;
model->fine = false;
model->ARR = 511;
model->CCR = 255;
model->pos = 0;
},
true);
lfrfid_debug_view_tune_clean(tune_view);
view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback);
view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback);
@@ -199,6 +201,8 @@ void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) {
model->ARR = 511;
model->CCR = 255;
model->pos = 0;
model->update_callback = NULL;
model->update_context = NULL;
},
true);
}
@@ -232,3 +236,17 @@ uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) {
return result;
}
void lfrfid_debug_view_tune_set_callback(
LfRfidTuneView* tune_view,
void (*callback)(void* context),
void* context) {
with_view_model(
tune_view->view,
LfRfidTuneViewModel * model,
{
model->update_callback = callback;
model->update_context = context;
},
false);
}
@@ -16,3 +16,8 @@ bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view);
uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view);
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view);
void lfrfid_debug_view_tune_set_callback(
LfRfidTuneView* tune_view,
void (*callback)(void* context),
void* context);
@@ -0,0 +1,11 @@
App(
appid="speaker_debug",
name="Speaker Debug",
apptype=FlipperAppType.DEBUG,
entry_point="speaker_debug_app",
requires=["gui", "notification"],
stack_size=2 * 1024,
order=10,
fap_category="Debug",
fap_libs=["music_worker"],
)
@@ -0,0 +1,120 @@
#include <furi.h>
#include <notification/notification.h>
#include <music_worker/music_worker.h>
#include <cli/cli.h>
#include <toolbox/args.h>
#define TAG "SpeakerDebug"
#define CLI_COMMAND "speaker_debug"
typedef enum {
SpeakerDebugAppMessageTypeStop,
} SpeakerDebugAppMessageType;
typedef struct {
SpeakerDebugAppMessageType type;
} SpeakerDebugAppMessage;
typedef struct {
MusicWorker* music_worker;
FuriMessageQueue* message_queue;
Cli* cli;
} SpeakerDebugApp;
static SpeakerDebugApp* speaker_app_alloc() {
SpeakerDebugApp* app = (SpeakerDebugApp*)malloc(sizeof(SpeakerDebugApp));
app->music_worker = music_worker_alloc();
app->message_queue = furi_message_queue_alloc(8, sizeof(SpeakerDebugAppMessage));
app->cli = furi_record_open(RECORD_CLI);
return app;
}
static void speaker_app_free(SpeakerDebugApp* app) {
music_worker_free(app->music_worker);
furi_message_queue_free(app->message_queue);
furi_record_close(RECORD_CLI);
free(app);
}
static void speaker_app_cli(Cli* cli, FuriString* args, void* context) {
UNUSED(cli);
SpeakerDebugApp* app = (SpeakerDebugApp*)context;
SpeakerDebugAppMessage message;
FuriString* cmd = furi_string_alloc();
if(!args_read_string_and_trim(args, cmd)) {
furi_string_free(cmd);
printf("Usage:\r\n");
printf("\t" CLI_COMMAND " stop\r\n");
return;
}
if(furi_string_cmp(cmd, "stop") == 0) {
message.type = SpeakerDebugAppMessageTypeStop;
FuriStatus status = furi_message_queue_put(app->message_queue, &message, 100);
if(status != FuriStatusOk) {
printf("Failed to send message\r\n");
} else {
printf("Stopping\r\n");
}
} else {
printf("Usage:\r\n");
printf("\t" CLI_COMMAND " stop\r\n");
}
furi_string_free(cmd);
}
static bool speaker_app_music_play(SpeakerDebugApp* app, const char* rtttl) {
if(music_worker_is_playing(app->music_worker)) {
music_worker_stop(app->music_worker);
}
if(!music_worker_load_rtttl_from_string(app->music_worker, rtttl)) {
FURI_LOG_E(TAG, "Failed to load RTTTL");
return false;
}
music_worker_set_volume(app->music_worker, 1.0f);
music_worker_start(app->music_worker);
return true;
}
static void speaker_app_music_stop(SpeakerDebugApp* app) {
if(music_worker_is_playing(app->music_worker)) {
music_worker_stop(app->music_worker);
}
}
static void speaker_app_run(SpeakerDebugApp* app, const char* arg) {
if(!arg || !speaker_app_music_play(app, arg)) {
FURI_LOG_E(TAG, "Provided RTTTL is invalid");
return;
}
cli_add_command(app->cli, CLI_COMMAND, CliCommandFlagParallelSafe, speaker_app_cli, app);
SpeakerDebugAppMessage message;
FuriStatus status;
while(true) {
status = furi_message_queue_get(app->message_queue, &message, FuriWaitForever);
if(status == FuriStatusOk) {
if(message.type == SpeakerDebugAppMessageTypeStop) {
speaker_app_music_stop(app);
break;
}
}
}
cli_delete_command(app->cli, CLI_COMMAND);
}
int32_t speaker_debug_app(void* arg) {
SpeakerDebugApp* app = speaker_app_alloc();
speaker_app_run(app, arg);
speaker_app_free(app);
return 0;
}
+16 -4
View File
@@ -10,6 +10,8 @@
#define LINES_ON_SCREEN 6
#define COLUMNS_ON_SCREEN 21
#define TAG "UartEcho"
#define DEFAULT_BAUD_RATE 230400
typedef struct UartDumpModel UartDumpModel;
@@ -179,7 +181,7 @@ static int32_t uart_echo_worker(void* context) {
return 0;
}
static UartEchoApp* uart_echo_app_alloc() {
static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
UartEchoApp* app = malloc(sizeof(UartEchoApp));
app->rx_stream = furi_stream_buffer_alloc(2048, 1);
@@ -220,7 +222,7 @@ static UartEchoApp* uart_echo_app_alloc() {
// Enable uart listener
furi_hal_console_disable();
furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200);
furi_hal_uart_set_br(FuriHalUartIdUSART1, baudrate);
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
return app;
@@ -263,8 +265,18 @@ static void uart_echo_app_free(UartEchoApp* app) {
}
int32_t uart_echo_app(void* p) {
UNUSED(p);
UartEchoApp* app = uart_echo_app_alloc();
uint32_t baudrate = DEFAULT_BAUD_RATE;
if(p) {
const char* baudrate_str = p;
if(sscanf(baudrate_str, "%lu", &baudrate) != 1) {
FURI_LOG_E(TAG, "Invalid baudrate: %s", baudrate_str);
baudrate = DEFAULT_BAUD_RATE;
}
}
FURI_LOG_I(TAG, "Using baudrate: %lu", baudrate);
UartEchoApp* app = uart_echo_app_alloc(baudrate);
view_dispatcher_run(app->view_dispatcher);
uart_echo_app_free(app);
return 0;
@@ -0,0 +1,32 @@
#include <dialogs/dialogs.h>
#include "../minunit.h"
MU_TEST(test_dialog_file_browser_set_basic_options_should_init_all_fields) {
mu_assert(
sizeof(DialogsFileBrowserOptions) == 28,
"Changes to `DialogsFileBrowserOptions` should also be reflected in `dialog_file_browser_set_basic_options`");
DialogsFileBrowserOptions options;
dialog_file_browser_set_basic_options(&options, ".fap", NULL);
// note: this assertions can safely be changed, their primary purpose is to remind the maintainer
// to update `dialog_file_browser_set_basic_options` by including all structure fields in it
mu_assert_string_eq(".fap", options.extension);
mu_assert_null(options.base_path);
mu_assert(options.skip_assets, "`skip_assets` should default to `true");
mu_assert(options.hide_dot_files, "`hide_dot_files` should default to `true");
mu_assert_null(options.icon);
mu_assert(options.hide_ext, "`hide_ext` should default to `true");
mu_assert_null(options.item_loader_callback);
mu_assert_null(options.item_loader_context);
}
MU_TEST_SUITE(dialogs_file_browser_options) {
MU_RUN_TEST(test_dialog_file_browser_set_basic_options_should_init_all_fields);
}
int run_minunit_test_dialogs_file_browser_options() {
MU_RUN_SUITE(dialogs_file_browser_options);
return MU_EXIT_CODE;
}
@@ -27,6 +27,7 @@ int run_minunit_test_nfc();
int run_minunit_test_bit_lib();
int run_minunit_test_float_tools();
int run_minunit_test_bt();
int run_minunit_test_dialogs_file_browser_options();
typedef int (*UnitTestEntry)();
@@ -55,6 +56,8 @@ const UnitTest unit_tests[] = {
{.name = "bit_lib", .entry = run_minunit_test_bit_lib},
{.name = "float_tools", .entry = run_minunit_test_float_tools},
{.name = "bt", .entry = run_minunit_test_bt},
{.name = "dialogs_file_browser_options",
.entry = run_minunit_test_dialogs_file_browser_options},
};
void minunit_print_progress() {