From 420c03bb58aae0fa526e555d7a92e14f43b7fa6e Mon Sep 17 00:00:00 2001 From: gornekich Date: Thu, 2 Sep 2021 02:22:40 +0300 Subject: [PATCH 1/5] [FL-1720] BLE GUI refactoring (#678) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * dialog_ex: add clean method, fix documentation * application: add bt debug and settings application * bt: add debug application * bt: add settings application * bt: rework bt service * bt debug: fix carrier debug app * assets: add debug animation to main menu * bt debug: fix bt packet test * bt service: rework bt service * bt: cleanup * Assets: fix spelling * Ble: wait for core 2 startup complete before initializing radio stack. * Accessor: remove dead code, switch port PA6 to PA4, because interrupt line 6 is used by down button. * FuriHal: assert interrupt line on add_int_callback. * Bt: update icon on core2 startup complete. Co-authored-by: あく --- applications/accessor/accessor-app.cpp | 10 - applications/accessor/helpers/wiegand.cpp | 13 +- applications/applications.c | 10 + applications/bt/bt.c | 266 ----------- applications/bt/bt_debug_app/bt_debug_app.c | 94 ++++ applications/bt/bt_debug_app/bt_debug_app.h | 26 ++ .../bt/bt_debug_app/views/bt_carrier_test.c | 188 ++++++++ .../bt/bt_debug_app/views/bt_carrier_test.h | 10 + .../bt/bt_debug_app/views/bt_packet_test.c | 155 +++++++ .../bt/bt_debug_app/views/bt_packet_test.h | 10 + applications/bt/bt_debug_app/views/bt_test.c | 422 ++++++++++++++++++ applications/bt/bt_debug_app/views/bt_test.h | 46 ++ .../bt/bt_debug_app/views/bt_test_types.h | 30 ++ applications/bt/bt_i.h | 53 --- applications/bt/bt_service/bt.c | 74 +++ applications/bt/{ => bt_service}/bt.h | 0 applications/bt/bt_service/bt_i.h | 29 ++ applications/bt/bt_settings.c | 50 +++ applications/bt/bt_settings.h | 15 + .../bt/bt_settings_app/bt_settings_app.c | 67 +++ .../bt/bt_settings_app/bt_settings_app.h | 27 ++ .../scenes/bt_settings_scene.c | 30 ++ .../scenes/bt_settings_scene.h | 29 ++ .../scenes/bt_settings_scene_config.h | 2 + .../scenes/bt_settings_scene_disable_dialog.c | 44 ++ .../scenes/bt_settings_scene_start.c | 56 +++ applications/bt/bt_types.h | 65 --- applications/bt/bt_views.c | 250 ----------- applications/bt/bt_views.h | 54 --- applications/gui/modules/dialog_ex.c | 19 + applications/gui/modules/dialog_ex.h | 36 +- applications/loader/loader.c | 2 +- assets/compiled/assets_icons.c | 39 +- assets/compiled/assets_icons.h | 9 +- assets/icons/MainMenu/Debug_14/frame_01.png | Bin 0 -> 3704 bytes assets/icons/MainMenu/Debug_14/frame_02.png | Bin 0 -> 3713 bytes assets/icons/MainMenu/Debug_14/frame_03.png | Bin 0 -> 3716 bytes assets/icons/MainMenu/Debug_14/frame_04.png | Bin 0 -> 3717 bytes assets/icons/MainMenu/Debug_14/frame_rate | 1 + .../{GubGHz => SubGhz}/Scanning_123x52.png | Bin assets/icons/{GubGHz => SubGhz}/lock_7x8.png | Bin assets/icons/{GubGHz => SubGhz}/quest_7x8.png | Bin .../icons/{GubGHz => SubGhz}/unlock_7x8.png | Bin firmware/targets/f6/furi-hal/furi-hal-bt.c | 6 +- firmware/targets/f6/furi-hal/furi-hal-gpio.c | 1 + .../targets/furi-hal-include/furi-hal-bt.h | 3 + 46 files changed, 1497 insertions(+), 744 deletions(-) delete mode 100644 applications/bt/bt.c create mode 100755 applications/bt/bt_debug_app/bt_debug_app.c create mode 100644 applications/bt/bt_debug_app/bt_debug_app.h create mode 100755 applications/bt/bt_debug_app/views/bt_carrier_test.c create mode 100644 applications/bt/bt_debug_app/views/bt_carrier_test.h create mode 100644 applications/bt/bt_debug_app/views/bt_packet_test.c create mode 100644 applications/bt/bt_debug_app/views/bt_packet_test.h create mode 100755 applications/bt/bt_debug_app/views/bt_test.c create mode 100755 applications/bt/bt_debug_app/views/bt_test.h create mode 100644 applications/bt/bt_debug_app/views/bt_test_types.h delete mode 100644 applications/bt/bt_i.h create mode 100644 applications/bt/bt_service/bt.c rename applications/bt/{ => bt_service}/bt.h (100%) create mode 100644 applications/bt/bt_service/bt_i.h create mode 100644 applications/bt/bt_settings.c create mode 100644 applications/bt/bt_settings.h create mode 100755 applications/bt/bt_settings_app/bt_settings_app.c create mode 100644 applications/bt/bt_settings_app/bt_settings_app.h create mode 100644 applications/bt/bt_settings_app/scenes/bt_settings_scene.c create mode 100644 applications/bt/bt_settings_app/scenes/bt_settings_scene.h create mode 100644 applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h create mode 100755 applications/bt/bt_settings_app/scenes/bt_settings_scene_disable_dialog.c create mode 100755 applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c delete mode 100644 applications/bt/bt_types.h delete mode 100755 applications/bt/bt_views.c delete mode 100644 applications/bt/bt_views.h mode change 100644 => 100755 applications/gui/modules/dialog_ex.c create mode 100644 assets/icons/MainMenu/Debug_14/frame_01.png create mode 100644 assets/icons/MainMenu/Debug_14/frame_02.png create mode 100644 assets/icons/MainMenu/Debug_14/frame_03.png create mode 100644 assets/icons/MainMenu/Debug_14/frame_04.png create mode 100644 assets/icons/MainMenu/Debug_14/frame_rate rename assets/icons/{GubGHz => SubGhz}/Scanning_123x52.png (100%) rename assets/icons/{GubGHz => SubGhz}/lock_7x8.png (100%) rename assets/icons/{GubGHz => SubGhz}/quest_7x8.png (100%) rename assets/icons/{GubGHz => SubGhz}/unlock_7x8.png (100%) diff --git a/applications/accessor/accessor-app.cpp b/applications/accessor/accessor-app.cpp index b462ec79..7313474b 100644 --- a/applications/accessor/accessor-app.cpp +++ b/applications/accessor/accessor-app.cpp @@ -109,16 +109,6 @@ void AccessorApp::notify_green_blink() { void AccessorApp::notify_success() { notification_message(notification, &sequence_success); - - hal_pwm_set(0.5, 1760 / 2, &htim2, TIM_CHANNEL_2); - delay(100); - hal_pwm_stop(&htim2, TIM_CHANNEL_2); - - delay(100); - - hal_pwm_set(0.5, 1760, &htim2, TIM_CHANNEL_2); - delay(100); - hal_pwm_stop(&htim2, TIM_CHANNEL_2); } /*************************** TEXT STORE *****************************/ diff --git a/applications/accessor/helpers/wiegand.cpp b/applications/accessor/helpers/wiegand.cpp index 9e92a15d..777fa561 100644 --- a/applications/accessor/helpers/wiegand.cpp +++ b/applications/accessor/helpers/wiegand.cpp @@ -11,6 +11,8 @@ volatile int WIEGAND::_bitCount = 0; int WIEGAND::_wiegandType = 0; constexpr uint32_t clocks_in_ms = 64 * 1000; +const GpioPin* pinD0 = &gpio_ext_pa4; +const GpioPin* pinD1 = &gpio_ext_pa7; WIEGAND::WIEGAND() { } @@ -53,9 +55,6 @@ void WIEGAND::begin() { _wiegandType = 0; _bitCount = 0; - const GpioPin* pinD0 = &gpio_ext_pa6; - const GpioPin* pinD1 = &gpio_ext_pa7; - hal_gpio_init_simple(pinD0, GpioModeInterruptFall); // Set D0 pin as input hal_gpio_init_simple(pinD1, GpioModeInterruptFall); // Set D1 pin as input @@ -64,11 +63,11 @@ void WIEGAND::begin() { } void WIEGAND::end() { - hal_gpio_remove_int_callback(&gpio_ext_pa6); - hal_gpio_remove_int_callback(&gpio_ext_pa7); + hal_gpio_remove_int_callback(pinD0); + hal_gpio_remove_int_callback(pinD1); - hal_gpio_init_simple(&gpio_ext_pa6, GpioModeAnalog); - hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog); + hal_gpio_init_simple(pinD0, GpioModeAnalog); + hal_gpio_init_simple(pinD1, GpioModeAnalog); } void WIEGAND::ReadD0() { diff --git a/applications/applications.c b/applications/applications.c index 36751e09..cd7e9f4e 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -32,6 +32,7 @@ extern int32_t scened_app(void* p); extern int32_t storage_test_app(void* p); extern int32_t subghz_app(void* p); extern int32_t vibro_test_app(void* p); +extern int32_t bt_debug_app(void* p); // Plugins extern int32_t music_player_app(void* p); @@ -48,6 +49,7 @@ extern void subghz_cli_init(); // Settings extern int32_t notification_settings_app(void* p); extern int32_t storage_settings_app(void* p); +extern int32_t bt_settings_app(void* p); const FlipperApplication FLIPPER_SERVICES[] = { /* Services */ @@ -236,6 +238,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = { #ifdef APP_LF_RFID {.app = lfrfid_debug_app, .name = "LF-RFID Debug", .stack_size = 1024, .icon = &A_125khz_14}, #endif + +#ifdef SRV_BT + {.app = bt_debug_app, .name = "Bluetooth Debug", .stack_size = 1024, .icon = NULL}, +#endif }; const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication); @@ -254,6 +260,10 @@ const FlipperApplication FLIPPER_SETTINGS_APPS[] = { #ifdef SRV_STORAGE {.app = storage_settings_app, .name = "Storage", .stack_size = 2048, .icon = NULL}, #endif + +#ifdef SRV_BT + {.app = bt_settings_app, .name = "Bluetooth", .stack_size = 1024, .icon = NULL}, +#endif }; const size_t FLIPPER_SETTINGS_APPS_COUNT = diff --git a/applications/bt/bt.c b/applications/bt/bt.c deleted file mode 100644 index 41974f65..00000000 --- a/applications/bt/bt.c +++ /dev/null @@ -1,266 +0,0 @@ -#include "bt_i.h" - -uint32_t bt_view_exit(void* context) { - (void)context; - return VIEW_NONE; -} - -void bt_update_statusbar(void* arg) { - furi_assert(arg); - Bt* bt = arg; - BtMessage m = {.type = BtMessageTypeUpdateStatusbar}; - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); -} - -void bt_update_param(void* arg) { - furi_assert(arg); - Bt* bt = arg; - BtMessage m; - if(bt->state.type == BtStateHoppingTx || bt->state.type == BtStateCarrierRxRunning) { - m.type = BtMessageTypeStartTestCarrier; - } else if(bt->state.type == BtStatePacketRunning) { - m.type = BtMessageTypeStartTestPacketRx; - } - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); -} - -Bt* bt_alloc() { - Bt* bt = furi_alloc(sizeof(Bt)); - - bt->message_queue = osMessageQueueNew(8, sizeof(BtMessage), NULL); - bt->update_status_timer = osTimerNew(bt_update_statusbar, osTimerPeriodic, bt, NULL); - osTimerStart(bt->update_status_timer, 4000); - bt->update_param_timer = osTimerNew(bt_update_param, osTimerPeriodic, bt, NULL); - bt->gui = furi_record_open("gui"); - bt->menu = furi_record_open("menu"); - - bt->state.type = BtStateReady; - bt->state.param.channel = BtChannel2402; - bt->state.param.power = BtPower0dB; - bt->state.param.datarate = BtDataRate1M; - - bt->statusbar_view_port = view_port_alloc(); - view_port_set_width(bt->statusbar_view_port, 5); - view_port_draw_callback_set(bt->statusbar_view_port, bt_draw_statusbar_callback, bt); - view_port_enabled_set(bt->statusbar_view_port, false); - gui_add_view_port(bt->gui, bt->statusbar_view_port, GuiLayerStatusBarLeft); - - bt->menu_icon = icon_animation_alloc(&A_Bluetooth_14); - bt->menu_item = menu_item_alloc_menu("Bluetooth", bt->menu_icon); - menu_item_subitem_add( - bt->menu_item, menu_item_alloc_function("Carrier test", NULL, bt_menu_test_carrier, bt)); - menu_item_subitem_add( - bt->menu_item, - menu_item_alloc_function("Test packet TX", NULL, bt_menu_test_packet_tx, bt)); - menu_item_subitem_add( - bt->menu_item, menu_item_alloc_function("Start app", NULL, bt_menu_start_app, bt)); - menu_item_subitem_add( - bt->menu_item, - menu_item_alloc_function("Test packet RX", NULL, bt_menu_test_packet_rx, bt)); - - // Carrier test - bt->view_test_carrier = view_alloc(); - view_set_context(bt->view_test_carrier, bt); - view_set_draw_callback(bt->view_test_carrier, bt_view_test_carrier_draw); - view_allocate_model( - bt->view_test_carrier, ViewModelTypeLocking, sizeof(BtViewTestCarrierModel)); - view_set_input_callback(bt->view_test_carrier, bt_view_test_carrier_input); - - // Packet TX test - bt->view_test_packet_tx = view_alloc(); - view_set_context(bt->view_test_packet_tx, bt); - view_set_draw_callback(bt->view_test_packet_tx, bt_view_test_packet_tx_draw); - view_allocate_model( - bt->view_test_packet_tx, ViewModelTypeLocking, sizeof(BtViewTestPacketTxModel)); - view_set_input_callback(bt->view_test_packet_tx, bt_view_test_packet_tx_input); - - // Packet RX test - bt->view_test_packet_rx = view_alloc(); - view_set_context(bt->view_test_packet_rx, bt); - view_set_draw_callback(bt->view_test_packet_rx, bt_view_test_packet_rx_draw); - view_allocate_model( - bt->view_test_packet_rx, ViewModelTypeLocking, sizeof(BtViewTestPacketRxModel)); - view_set_input_callback(bt->view_test_packet_rx, bt_view_test_packet_rx_input); - - // Start app - bt->view_start_app = view_alloc(); - view_set_context(bt->view_start_app, bt); - view_set_draw_callback(bt->view_start_app, bt_view_app_draw); - view_set_previous_callback(bt->view_start_app, bt_view_exit); - - // View dispatcher - bt->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_add_view(bt->view_dispatcher, BtViewTestCarrier, bt->view_test_carrier); - view_dispatcher_add_view(bt->view_dispatcher, BtViewTestPacketTx, bt->view_test_packet_tx); - view_dispatcher_add_view(bt->view_dispatcher, BtViewTestPacketRx, bt->view_test_packet_rx); - view_dispatcher_add_view(bt->view_dispatcher, BtViewStartApp, bt->view_start_app); - - Gui* gui = furi_record_open("gui"); - view_dispatcher_attach_to_gui(bt->view_dispatcher, gui, ViewDispatcherTypeFullscreen); - - with_value_mutex( - bt->menu, (Menu * menu) { menu_item_add(menu, bt->menu_item); }); - return bt; -} - -void bt_draw_statusbar_callback(Canvas* canvas, void* context) { - canvas_draw_icon(canvas, 0, 0, &I_Bluetooth_5x8); -} - -void bt_menu_test_carrier(void* context) { - furi_assert(context); - Bt* bt = context; - bt->state.type = BtStateCarrierTx; - BtMessage message = { - .type = BtMessageTypeStartTestCarrier, - .param.channel = bt->state.param.channel, - .param.power = bt->state.param.power}; - furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); -} - -void bt_menu_test_packet_tx(void* context) { - furi_assert(context); - Bt* bt = context; - bt->state.type = BtStatePacketSetup; - BtMessage message = { - .type = BtMessageTypeSetupTestPacketTx, - .param.channel = bt->state.param.channel, - .param.datarate = bt->state.param.datarate}; - furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); -} - -void bt_menu_test_packet_rx(void* context) { - furi_assert(context); - Bt* bt = context; - bt->state.type = BtStatePacketSetup; - BtMessage message = { - .type = BtMessageTypeSetupTestPacketRx, - .param.channel = bt->state.param.channel, - .param.datarate = bt->state.param.datarate}; - furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); -} - -void bt_menu_start_app(void* context) { - furi_assert(context); - Bt* bt = context; - bt->state.type = BtStateStartedApp; - BtMessage message = {.type = BtMessageTypeStartApp}; - furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); -} - -int32_t bt_srv() { - Bt* bt = bt_alloc(); - - furi_record_create("bt", bt); - - furi_hal_bt_init(); - BtMessage message; - while(1) { - furi_check(osMessageQueueGet(bt->message_queue, &message, NULL, osWaitForever) == osOK); - if(message.type == BtMessageTypeStartTestCarrier) { - // Start carrier test - furi_hal_bt_stop_tone_tx(); - if(bt->state.type == BtStateCarrierTx) { - furi_hal_bt_start_tone_tx(message.param.channel, message.param.power); - } else if(bt->state.type == BtStateHoppingTx) { - bt->state.param.channel = - bt_switch_channel(InputKeyRight, bt->state.param.channel); - furi_hal_bt_start_tone_tx(bt->state.param.channel, bt->state.param.power); - } else if(bt->state.type == BtStateCarrierRxStart) { - furi_hal_bt_start_packet_rx(bt->state.param.channel, bt->state.param.datarate); - bt->state.type = BtStateCarrierRxRunning; - } else if(bt->state.type == BtStateCarrierRxRunning) { - bt->state.param.rssi = furi_hal_bt_get_rssi(); - } - with_view_model( - bt->view_test_carrier, (BtViewTestCarrierModel * model) { - model->type = bt->state.type; - model->channel = bt->state.param.channel; - model->power = bt->state.param.power; - model->rssi = bt->state.param.rssi; - return true; - }); - view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewTestCarrier); - } else if(message.type == BtMessageTypeStopTestCarrier) { - if(bt->state.type == BtStateCarrierRxRunning) { - furi_hal_bt_stop_packet_test(); - } else { - furi_hal_bt_stop_tone_tx(); - } - bt->state.type = BtStateReady; - } else if(message.type == BtMessageTypeSetupTestPacketTx) { - // Update packet test setup - furi_hal_bt_stop_packet_test(); - with_view_model( - bt->view_test_packet_tx, (BtViewTestPacketTxModel * model) { - model->type = bt->state.type; - model->channel = bt->state.param.channel; - model->datarate = bt->state.param.datarate; - return true; - }); - view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewTestPacketTx); - } else if(message.type == BtMessageTypeStartTestPacketTx) { - // Start sending packets - if(bt->state.type == BtStatePacketStart) { - furi_hal_bt_start_packet_tx(message.param.channel, 1, message.param.datarate); - } else if(bt->state.type == BtStatePacketSetup) { - furi_hal_bt_stop_packet_test(); - bt->state.param.packets_sent = furi_hal_bt_get_transmitted_packets(); - } - with_view_model( - bt->view_test_packet_tx, (BtViewTestPacketTxModel * model) { - model->type = bt->state.type; - model->channel = bt->state.param.channel; - model->datarate = bt->state.param.datarate; - model->packets_sent = bt->state.param.packets_sent; - return true; - }); - view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewTestPacketTx); - } else if(message.type == BtMessageTypeSetupTestPacketRx) { - // Update packet test setup - furi_hal_bt_stop_packet_test(); - with_view_model( - bt->view_test_packet_rx, (BtViewTestPacketRxModel * model) { - model->type = bt->state.type; - model->channel = bt->state.param.channel; - model->datarate = bt->state.param.datarate; - return true; - }); - view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewTestPacketRx); - } else if(message.type == BtMessageTypeStartTestPacketRx) { - // Start test rx - if(bt->state.type == BtStatePacketStart) { - furi_hal_bt_start_packet_rx(message.param.channel, message.param.datarate); - bt->state.type = BtStatePacketRunning; - } else if(bt->state.type == BtStatePacketRunning) { - bt->state.param.rssi = furi_hal_bt_get_rssi(); - } else if(bt->state.type == BtStatePacketSetup) { - bt->state.param.packets_received = furi_hal_bt_stop_packet_test(); - } - with_view_model( - bt->view_test_packet_rx, (BtViewTestPacketRxModel * model) { - model->type = bt->state.type; - model->channel = bt->state.param.channel; - model->datarate = bt->state.param.datarate; - model->packets_received = bt->state.param.packets_received; - model->rssi = bt->state.param.rssi; - return true; - }); - view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewTestPacketRx); - } else if(message.type == BtMessageTypeStopTestPacket) { - // Stop test packet tx - furi_hal_bt_stop_packet_test(); - bt->state.type = BtStateReady; - } else if(message.type == BtMessageTypeStartApp) { - // Start app - view_dispatcher_switch_to_view(bt->view_dispatcher, BtViewStartApp); - if(furi_hal_bt_start_app()) { - bt->state.type = BtStateStartedApp; - } - } else if(message.type == BtMessageTypeUpdateStatusbar) { - // Update statusbar - view_port_enabled_set(bt->statusbar_view_port, furi_hal_bt_is_alive()); - } - } - return 0; -} diff --git a/applications/bt/bt_debug_app/bt_debug_app.c b/applications/bt/bt_debug_app/bt_debug_app.c new file mode 100755 index 00000000..1511e84f --- /dev/null +++ b/applications/bt/bt_debug_app/bt_debug_app.c @@ -0,0 +1,94 @@ +#include "bt_debug_app.h" + +enum BtDebugSubmenuIndex { + BtDebugSubmenuIndexCarrierTest, + BtDebugSubmenuIndexPacketTest, +}; + +void bt_debug_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + BtDebugApp* app = context; + if(index == BtDebugSubmenuIndexCarrierTest) { + view_dispatcher_switch_to_view(app->view_dispatcher, BtDebugAppViewCarrierTest); + } else if(index == BtDebugSubmenuIndexPacketTest) { + view_dispatcher_switch_to_view(app->view_dispatcher, BtDebugAppViewPacketTest); + } +} + +uint32_t bt_debug_exit(void* context) { + return VIEW_NONE; +} + +uint32_t bt_debug_start_view(void* context) { + return BtDebugAppViewSubmenu; +} + +BtDebugApp* bt_debug_app_alloc() { + BtDebugApp* app = furi_alloc(sizeof(BtDebugApp)); + // Gui + app->gui = furi_record_open("gui"); + + // View dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // Views + app->submenu = submenu_alloc(); + submenu_add_item( + app->submenu, + "Carrier test", + BtDebugSubmenuIndexCarrierTest, + bt_debug_submenu_callback, + app); + submenu_add_item( + app->submenu, "Packet test", BtDebugSubmenuIndexPacketTest, bt_debug_submenu_callback, app); + view_set_previous_callback(submenu_get_view(app->submenu), bt_debug_exit); + view_dispatcher_add_view( + app->view_dispatcher, BtDebugAppViewSubmenu, submenu_get_view(app->submenu)); + app->bt_carrier_test = bt_carrier_test_alloc(); + view_set_previous_callback( + bt_carrier_test_get_view(app->bt_carrier_test), bt_debug_start_view); + view_dispatcher_add_view( + app->view_dispatcher, + BtDebugAppViewCarrierTest, + bt_carrier_test_get_view(app->bt_carrier_test)); + app->bt_packet_test = bt_packet_test_alloc(); + view_set_previous_callback(bt_packet_test_get_view(app->bt_packet_test), bt_debug_start_view); + view_dispatcher_add_view( + app->view_dispatcher, + BtDebugAppViewPacketTest, + bt_packet_test_get_view(app->bt_packet_test)); + + // Switch to menu + view_dispatcher_switch_to_view(app->view_dispatcher, BtDebugAppViewSubmenu); + + return app; +} + +void bt_debug_app_free(BtDebugApp* app) { + furi_assert(app); + + // Free views + view_dispatcher_remove_view(app->view_dispatcher, BtDebugAppViewSubmenu); + submenu_free(app->submenu); + view_dispatcher_remove_view(app->view_dispatcher, BtDebugAppViewCarrierTest); + bt_carrier_test_free(app->bt_carrier_test); + view_dispatcher_remove_view(app->view_dispatcher, BtDebugAppViewPacketTest); + bt_packet_test_free(app->bt_packet_test); + view_dispatcher_free(app->view_dispatcher); + + // Close gui record + furi_record_close("gui"); + app->gui = NULL; + + // Free rest + free(app); +} + +int32_t bt_debug_app(void* p) { + BtDebugApp* app = bt_debug_app_alloc(); + view_dispatcher_run(app->view_dispatcher); + bt_debug_app_free(app); + return 0; +} diff --git a/applications/bt/bt_debug_app/bt_debug_app.h b/applications/bt/bt_debug_app/bt_debug_app.h new file mode 100644 index 00000000..ceb0e934 --- /dev/null +++ b/applications/bt/bt_debug_app/bt_debug_app.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include "views/bt_carrier_test.h" +#include "views/bt_packet_test.h" +#include "../bt_settings.h" + +typedef struct { + BtSettings settings; + Gui* gui; + ViewDispatcher* view_dispatcher; + Submenu* submenu; + BtCarrierTest* bt_carrier_test; + BtPacketTest* bt_packet_test; +} BtDebugApp; + +typedef enum { + BtDebugAppViewSubmenu, + BtDebugAppViewCarrierTest, + BtDebugAppViewPacketTest, +} BtDebugAppView; diff --git a/applications/bt/bt_debug_app/views/bt_carrier_test.c b/applications/bt/bt_debug_app/views/bt_carrier_test.c new file mode 100755 index 00000000..2343c861 --- /dev/null +++ b/applications/bt/bt_debug_app/views/bt_carrier_test.c @@ -0,0 +1,188 @@ +#include "bt_carrier_test.h" +#include "bt_test.h" +#include "bt_test_types.h" +#include "furi-hal-bt.h" + +struct BtCarrierTest { + BtTest* bt_test; + BtTestParam* bt_param_channel; + BtTestMode mode; + BtTestChannel channel; + BtTestPower power; + osTimerId_t timer; +}; + +static BtTestParamValue bt_param_mode[] = { + {.value = BtTestModeRx, .str = "Rx"}, + {.value = BtTestModeTx, .str = "Tx"}, + {.value = BtTestModeTxHopping, .str = "Hopping Tx"}, +}; + +static BtTestParamValue bt_param_channel[] = { + {.value = BtTestChannel2402, .str = "2402 MHz"}, + {.value = BtTestChannel2440, .str = "2440 MHz"}, + {.value = BtTestChannel2480, .str = "2480 MHz"}, +}; + +static BtTestParamValue bt_param_power[] = { + {.value = BtPower0dB, .str = "0 dB"}, + {.value = BtPower2dB, .str = "2 dB"}, + {.value = BtPower4dB, .str = "4 dB"}, + {.value = BtPower6dB, .str = "6 dB"}, +}; + +static void bt_carrier_test_start(BtCarrierTest* bt_carrier_test) { + furi_assert(bt_carrier_test); + if(bt_carrier_test->mode == BtTestModeRx) { + furi_hal_bt_start_packet_rx(bt_carrier_test->channel, 1); + osTimerStart(bt_carrier_test->timer, 1024 / 4); + } else if(bt_carrier_test->mode == BtTestModeTxHopping) { + furi_hal_bt_start_tone_tx(bt_carrier_test->channel, bt_carrier_test->power); + osTimerStart(bt_carrier_test->timer, 2048); + } else if(bt_carrier_test->mode == BtTestModeTx) { + furi_hal_bt_start_tone_tx(bt_carrier_test->channel, bt_carrier_test->power); + } +} + +static void bt_carrier_test_switch_channel(BtCarrierTest* bt_carrier_test) { + furi_assert(bt_carrier_test); + furi_hal_bt_stop_tone_tx(); + uint8_t channel_i = 0; + if(bt_carrier_test->channel == BtTestChannel2402) { + bt_carrier_test->channel = BtTestChannel2440; + channel_i = 1; + } else if(bt_carrier_test->channel == BtTestChannel2440) { + bt_carrier_test->channel = BtTestChannel2480; + channel_i = 2; + } else if(bt_carrier_test->channel == BtTestChannel2480) { + bt_carrier_test->channel = BtTestChannel2402; + channel_i = 0; + } + furi_hal_bt_start_tone_tx(bt_carrier_test->channel, bt_carrier_test->power); + bt_test_set_current_value_index(bt_carrier_test->bt_param_channel, channel_i); + bt_test_set_current_value_text( + bt_carrier_test->bt_param_channel, bt_param_channel[channel_i].str); +} + +static void bt_carrier_test_stop(BtCarrierTest* bt_carrier_test) { + furi_assert(bt_carrier_test); + if(bt_carrier_test->mode == BtTestModeTxHopping) { + furi_hal_bt_stop_tone_tx(); + osTimerStop(bt_carrier_test->timer); + } else if(bt_carrier_test->mode == BtTestModeTx) { + furi_hal_bt_stop_tone_tx(); + } else if(bt_carrier_test->mode == BtTestModeRx) { + furi_hal_bt_stop_packet_test(); + osTimerStop(bt_carrier_test->timer); + } +} + +static uint32_t bt_carrier_test_param_changed(BtTestParam* param, BtTestParamValue* param_val) { + furi_assert(param); + uint8_t index = bt_test_get_current_value_index(param); + bt_test_set_current_value_text(param, param_val[index].str); + return param_val[index].value; +} + +static void bt_carrier_test_mode_changed(BtTestParam* param) { + BtCarrierTest* bt_carrier_test = bt_test_get_context(param); + bt_carrier_test_stop(bt_carrier_test); + bt_carrier_test->mode = bt_carrier_test_param_changed(param, bt_param_mode); +} + +static void bt_carrier_test_channel_changed(BtTestParam* param) { + BtCarrierTest* bt_carrier_test = bt_test_get_context(param); + bt_carrier_test_stop(bt_carrier_test); + bt_carrier_test->channel = bt_carrier_test_param_changed(param, bt_param_channel); +} + +static void bt_carrier_test_param_channel(BtTestParam* param) { + BtCarrierTest* bt_carrier_test = bt_test_get_context(param); + bt_carrier_test_stop(bt_carrier_test); + bt_carrier_test->power = bt_carrier_test_param_changed(param, bt_param_power); +} + +static void bt_carrier_test_change_state_callback(BtTestState state, void* context) { + furi_assert(context); + BtCarrierTest* bt_carrier_test = context; + furi_hal_bt_stop_tone_tx(); + if(state == BtTestStateStarted) { + bt_carrier_test_start(bt_carrier_test); + } else if(state == BtTestStateStopped) { + bt_carrier_test_stop(bt_carrier_test); + } +} + +static void bt_carrier_test_exit_callback(void* context) { + furi_assert(context); + BtCarrierTest* bt_carrier_test = context; + bt_carrier_test_stop(bt_carrier_test); +} + +static void bt_test_carrier_timer_callback(void* context) { + furi_assert(context); + BtCarrierTest* bt_carrier_test = context; + if(bt_carrier_test->mode == BtTestModeRx) { + bt_test_set_rssi(bt_carrier_test->bt_test, furi_hal_bt_get_rssi()); + } else if(bt_carrier_test->mode == BtTestModeTxHopping) { + bt_carrier_test_switch_channel(bt_carrier_test); + } +} + +BtCarrierTest* bt_carrier_test_alloc() { + BtCarrierTest* bt_carrier_test = furi_alloc(sizeof(BtCarrierTest)); + bt_carrier_test->bt_test = bt_test_alloc(); + bt_test_set_context(bt_carrier_test->bt_test, bt_carrier_test); + bt_test_set_change_state_callback( + bt_carrier_test->bt_test, bt_carrier_test_change_state_callback); + bt_test_set_back_callback(bt_carrier_test->bt_test, bt_carrier_test_exit_callback); + + BtTestParam* param; + param = bt_test_param_add( + bt_carrier_test->bt_test, + "Mode", + SIZEOF_ARRAY(bt_param_mode), + bt_carrier_test_mode_changed, + bt_carrier_test); + bt_test_set_current_value_index(param, 0); + bt_test_set_current_value_text(param, bt_param_mode[0].str); + bt_carrier_test->mode = BtTestModeRx; + + param = bt_test_param_add( + bt_carrier_test->bt_test, + "Channel", + SIZEOF_ARRAY(bt_param_channel), + bt_carrier_test_channel_changed, + bt_carrier_test); + bt_test_set_current_value_index(param, 0); + bt_test_set_current_value_text(param, bt_param_channel[0].str); + bt_carrier_test->channel = BtTestChannel2402; + bt_carrier_test->bt_param_channel = param; + + param = bt_test_param_add( + bt_carrier_test->bt_test, + "Power", + SIZEOF_ARRAY(bt_param_power), + bt_carrier_test_param_channel, + bt_carrier_test); + bt_test_set_current_value_index(param, 0); + bt_test_set_current_value_text(param, bt_param_power[0].str); + bt_carrier_test->power = BtPower0dB; + + bt_carrier_test->timer = + osTimerNew(bt_test_carrier_timer_callback, osTimerPeriodic, bt_carrier_test, NULL); + + return bt_carrier_test; +} + +void bt_carrier_test_free(BtCarrierTest* bt_carrier_test) { + furi_assert(bt_carrier_test); + bt_test_free(bt_carrier_test->bt_test); + osTimerDelete(bt_carrier_test->timer); + free(bt_carrier_test); +} + +View* bt_carrier_test_get_view(BtCarrierTest* bt_carrier_test) { + furi_assert(bt_carrier_test); + return bt_test_get_view(bt_carrier_test->bt_test); +} diff --git a/applications/bt/bt_debug_app/views/bt_carrier_test.h b/applications/bt/bt_debug_app/views/bt_carrier_test.h new file mode 100644 index 00000000..51a40089 --- /dev/null +++ b/applications/bt/bt_debug_app/views/bt_carrier_test.h @@ -0,0 +1,10 @@ +#pragma once +#include + +typedef struct BtCarrierTest BtCarrierTest; + +BtCarrierTest* bt_carrier_test_alloc(); + +void bt_carrier_test_free(BtCarrierTest* bt_carrier_test); + +View* bt_carrier_test_get_view(BtCarrierTest* bt_carrier_test); diff --git a/applications/bt/bt_debug_app/views/bt_packet_test.c b/applications/bt/bt_debug_app/views/bt_packet_test.c new file mode 100644 index 00000000..192b88d1 --- /dev/null +++ b/applications/bt/bt_debug_app/views/bt_packet_test.c @@ -0,0 +1,155 @@ +#include "bt_packet_test.h" +#include "bt_test.h" +#include "bt_test_types.h" +#include "furi-hal-bt.h" + +struct BtPacketTest { + BtTest* bt_test; + BtTestMode mode; + BtTestChannel channel; + BtTestDataRate data_rate; + osTimerId_t timer; +}; + +static BtTestParamValue bt_param_mode[] = { + {.value = BtTestModeRx, .str = "Rx"}, + {.value = BtTestModeTx, .str = "Tx"}, +}; + +static BtTestParamValue bt_param_channel[] = { + {.value = BtTestChannel2402, .str = "2402 MHz"}, + {.value = BtTestChannel2440, .str = "2440 MHz"}, + {.value = BtTestChannel2480, .str = "2480 MHz"}, +}; + +static BtTestParamValue bt_param_data_rate[] = { + {.value = BtDataRate1M, .str = "1 Mbps"}, + {.value = BtDataRate2M, .str = "2 Mbps"}, +}; + +static void bt_packet_test_start(BtPacketTest* bt_packet_test) { + furi_assert(bt_packet_test); + if(bt_packet_test->mode == BtTestModeRx) { + furi_hal_bt_start_packet_rx(bt_packet_test->channel, bt_packet_test->data_rate); + osTimerStart(bt_packet_test->timer, 1024 / 4); + } else if(bt_packet_test->mode == BtTestModeTx) { + furi_hal_bt_start_packet_tx(bt_packet_test->channel, 1, bt_packet_test->data_rate); + } +} + +static void bt_packet_test_stop(BtPacketTest* bt_packet_test) { + furi_assert(bt_packet_test); + if(bt_packet_test->mode == BtTestModeTx) { + furi_hal_bt_stop_packet_test(); + bt_test_set_packets_tx(bt_packet_test->bt_test, furi_hal_bt_get_transmitted_packets()); + } else if(bt_packet_test->mode == BtTestModeRx) { + bt_test_set_packets_rx(bt_packet_test->bt_test, furi_hal_bt_stop_packet_test()); + osTimerStop(bt_packet_test->timer); + } +} + +static uint32_t bt_packet_test_param_changed(BtTestParam* param, BtTestParamValue* param_val) { + furi_assert(param); + uint8_t index = bt_test_get_current_value_index(param); + bt_test_set_current_value_text(param, param_val[index].str); + return param_val[index].value; +} + +static void bt_packet_test_mode_changed(BtTestParam* param) { + BtPacketTest* bt_packet_test = bt_test_get_context(param); + bt_packet_test_stop(bt_packet_test); + bt_packet_test->mode = bt_packet_test_param_changed(param, bt_param_mode); +} + +static void bt_packet_test_channel_changed(BtTestParam* param) { + BtPacketTest* bt_packet_test = bt_test_get_context(param); + bt_packet_test_stop(bt_packet_test); + bt_packet_test->channel = bt_packet_test_param_changed(param, bt_param_channel); +} + +static void bt_packet_test_param_channel(BtTestParam* param) { + BtPacketTest* bt_packet_test = bt_test_get_context(param); + bt_packet_test_stop(bt_packet_test); + bt_packet_test->data_rate = bt_packet_test_param_changed(param, bt_param_data_rate); +} + +static void bt_packet_test_change_state_callback(BtTestState state, void* context) { + furi_assert(context); + BtPacketTest* bt_packet_test = context; + if(state == BtTestStateStarted) { + bt_packet_test_start(bt_packet_test); + } else if(state == BtTestStateStopped) { + bt_packet_test_stop(bt_packet_test); + } +} + +static void bt_packet_test_exit_callback(void* context) { + furi_assert(context); + BtPacketTest* bt_packet_test = context; + bt_packet_test_stop(bt_packet_test); +} + +static void bt_test_packet_timer_callback(void* context) { + furi_assert(context); + BtPacketTest* bt_packet_test = context; + if(bt_packet_test->mode == BtTestModeRx) { + bt_test_set_rssi(bt_packet_test->bt_test, furi_hal_bt_get_rssi()); + } +} + +BtPacketTest* bt_packet_test_alloc() { + BtPacketTest* bt_packet_test = furi_alloc(sizeof(BtPacketTest)); + bt_packet_test->bt_test = bt_test_alloc(); + bt_test_set_context(bt_packet_test->bt_test, bt_packet_test); + bt_test_set_change_state_callback( + bt_packet_test->bt_test, bt_packet_test_change_state_callback); + bt_test_set_back_callback(bt_packet_test->bt_test, bt_packet_test_exit_callback); + + BtTestParam* param; + param = bt_test_param_add( + bt_packet_test->bt_test, + "Mode", + SIZEOF_ARRAY(bt_param_mode), + bt_packet_test_mode_changed, + bt_packet_test); + bt_test_set_current_value_index(param, 0); + bt_test_set_current_value_text(param, bt_param_mode[0].str); + bt_packet_test->mode = BtTestModeRx; + + param = bt_test_param_add( + bt_packet_test->bt_test, + "Channel", + SIZEOF_ARRAY(bt_param_channel), + bt_packet_test_channel_changed, + bt_packet_test); + bt_test_set_current_value_index(param, 0); + bt_test_set_current_value_text(param, bt_param_channel[0].str); + bt_packet_test->channel = BtTestChannel2402; + + param = bt_test_param_add( + bt_packet_test->bt_test, + "Data rate", + SIZEOF_ARRAY(bt_param_data_rate), + bt_packet_test_param_channel, + bt_packet_test); + bt_test_set_current_value_index(param, 0); + bt_test_set_current_value_text(param, bt_param_data_rate[0].str); + bt_packet_test->data_rate = BtDataRate1M; + + bt_packet_test->timer = + osTimerNew(bt_test_packet_timer_callback, osTimerPeriodic, bt_packet_test, NULL); + + return bt_packet_test; +} + +void bt_packet_test_free(BtPacketTest* bt_packet_test) { + furi_assert(bt_packet_test); + bt_test_free(bt_packet_test->bt_test); + osTimerDelete(bt_packet_test->timer); + free(bt_packet_test); +} + +View* bt_packet_test_get_view(BtPacketTest* bt_packet_test) { + furi_assert(bt_packet_test); + return bt_test_get_view(bt_packet_test->bt_test); +} diff --git a/applications/bt/bt_debug_app/views/bt_packet_test.h b/applications/bt/bt_debug_app/views/bt_packet_test.h new file mode 100644 index 00000000..8ea449b2 --- /dev/null +++ b/applications/bt/bt_debug_app/views/bt_packet_test.h @@ -0,0 +1,10 @@ +#pragma once +#include + +typedef struct BtPacketTest BtPacketTest; + +BtPacketTest* bt_packet_test_alloc(); + +void bt_packet_test_free(BtPacketTest* bt_packet_test); + +View* bt_packet_test_get_view(BtPacketTest* bt_packet_test); diff --git a/applications/bt/bt_debug_app/views/bt_test.c b/applications/bt/bt_debug_app/views/bt_test.c new file mode 100755 index 00000000..747ce6a4 --- /dev/null +++ b/applications/bt/bt_debug_app/views/bt_test.c @@ -0,0 +1,422 @@ +#include "bt_test.h" + +#include +#include +#include +#include +#include +#include + +struct BtTestParam { + const char* label; + uint8_t current_value_index; + string_t current_value_text; + uint8_t values_count; + BtTestParamChangeCallback change_callback; + void* context; +}; + +ARRAY_DEF(BtTestParamArray, BtTestParam, M_POD_OPLIST); + +struct BtTest { + View* view; + BtTestChangeStateCallback change_state_callback; + BtTestBackCallback back_callback; + void* context; +}; + +typedef struct { + BtTestState state; + BtTestParamArray_t params; + uint8_t position; + uint8_t window_position; + const char* message; + float rssi; + uint32_t packets_num_rx; + uint32_t packets_num_tx; +} BtTestModel; + +#define BT_TEST_START_MESSAGE "Ok - Start" +#define BT_TEST_STOP_MESSAGE "Ok - Stop" + +static void bt_test_process_up(BtTest* bt_test); +static void bt_test_process_down(BtTest* bt_test); +static void bt_test_process_left(BtTest* bt_test); +static void bt_test_process_right(BtTest* bt_test); +static void bt_test_process_ok(BtTest* bt_test); +static void bt_test_process_back(BtTest* bt_test); + +static void bt_test_draw_callback(Canvas* canvas, void* _model) { + BtTestModel* model = _model; + char info_str[32]; + + const uint8_t param_height = 16; + const uint8_t param_width = 123; + + canvas_clear(canvas); + + uint8_t position = 0; + BtTestParamArray_it_t it; + + canvas_set_font(canvas, FontSecondary); + for(BtTestParamArray_it(it, model->params); !BtTestParamArray_end_p(it); + BtTestParamArray_next(it)) { + uint8_t param_position = position - model->window_position; + uint8_t params_on_screen = 3; + uint8_t y_offset = 0; + + if(param_position < params_on_screen) { + const BtTestParam* param = BtTestParamArray_cref(it); + uint8_t param_y = y_offset + (param_position * param_height); + uint8_t param_text_y = param_y + param_height - 4; + + if(position == model->position) { + canvas_set_color(canvas, ColorBlack); + elements_slightly_rounded_box( + canvas, 0, param_y + 1, param_width, param_height - 2); + canvas_set_color(canvas, ColorWhite); + } else { + canvas_set_color(canvas, ColorBlack); + } + + canvas_draw_str(canvas, 6, param_text_y, param->label); + + if(param->current_value_index > 0) { + canvas_draw_str(canvas, 50, param_text_y, "<"); + } + + canvas_draw_str(canvas, 61, param_text_y, string_get_cstr(param->current_value_text)); + + if(param->current_value_index < (param->values_count - 1)) { + canvas_draw_str(canvas, 113, param_text_y, ">"); + } + } + + position++; + } + + elements_scrollbar(canvas, model->position, BtTestParamArray_size(model->params)); + canvas_draw_str(canvas, 6, 60, model->message); + if(model->state == BtTestStateStarted) { + if(model->rssi != 0.0f) { + snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", model->rssi); + canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); + } + } else if(model->state == BtTestStateStopped) { + if(model->packets_num_rx) { + snprintf(info_str, sizeof(info_str), "%ld pack rcv", model->packets_num_rx); + canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); + } else if(model->packets_num_tx) { + snprintf(info_str, sizeof(info_str), "%ld pack sent", model->packets_num_tx); + canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); + } + } +} + +static bool bt_test_input_callback(InputEvent* event, void* context) { + BtTest* bt_test = context; + furi_assert(bt_test); + bool consumed = false; + + if(event->type == InputTypeShort) { + switch(event->key) { + case InputKeyUp: + consumed = true; + bt_test_process_up(bt_test); + break; + case InputKeyDown: + consumed = true; + bt_test_process_down(bt_test); + break; + case InputKeyLeft: + consumed = true; + bt_test_process_left(bt_test); + break; + case InputKeyRight: + consumed = true; + bt_test_process_right(bt_test); + break; + case InputKeyOk: + consumed = true; + bt_test_process_ok(bt_test); + break; + case InputKeyBack: + consumed = false; + bt_test_process_back(bt_test); + break; + default: + break; + } + } + + return consumed; +} + +void bt_test_process_up(BtTest* bt_test) { + with_view_model( + bt_test->view, (BtTestModel * model) { + uint8_t params_on_screen = 3; + if(model->position > 0) { + model->position--; + if(((model->position - model->window_position) < 1) && + model->window_position > 0) { + model->window_position--; + } + } else { + model->position = BtTestParamArray_size(model->params) - 1; + if(model->position > (params_on_screen - 1)) { + model->window_position = model->position - (params_on_screen - 1); + } + } + return true; + }); +} + +void bt_test_process_down(BtTest* bt_test) { + with_view_model( + bt_test->view, (BtTestModel * model) { + uint8_t params_on_screen = 3; + if(model->position < (BtTestParamArray_size(model->params) - 1)) { + model->position++; + if((model->position - model->window_position) > (params_on_screen - 2) && + model->window_position < + (BtTestParamArray_size(model->params) - params_on_screen)) { + model->window_position++; + } + } else { + model->position = 0; + model->window_position = 0; + } + return true; + }); +} + +BtTestParam* bt_test_get_selected_param(BtTestModel* model) { + BtTestParam* param = NULL; + + BtTestParamArray_it_t it; + uint8_t position = 0; + for(BtTestParamArray_it(it, model->params); !BtTestParamArray_end_p(it); + BtTestParamArray_next(it)) { + if(position == model->position) { + break; + } + position++; + } + + param = BtTestParamArray_ref(it); + + furi_assert(param); + return param; +} + +void bt_test_process_left(BtTest* bt_test) { + BtTestParam* param; + with_view_model( + bt_test->view, (BtTestModel * model) { + param = bt_test_get_selected_param(model); + if(param->current_value_index > 0) { + param->current_value_index--; + if(param->change_callback) { + model->state = BtTestStateStopped; + model->message = BT_TEST_START_MESSAGE; + model->rssi = 0.0f; + model->packets_num_rx = 0; + model->packets_num_tx = 0; + } + } + return true; + }); + if(param->change_callback) { + param->change_callback(param); + } +} + +void bt_test_process_right(BtTest* bt_test) { + BtTestParam* param; + with_view_model( + bt_test->view, (BtTestModel * model) { + param = bt_test_get_selected_param(model); + if(param->current_value_index < (param->values_count - 1)) { + param->current_value_index++; + if(param->change_callback) { + model->state = BtTestStateStopped; + model->message = BT_TEST_START_MESSAGE; + model->rssi = 0.0f; + model->packets_num_rx = 0; + model->packets_num_tx = 0; + } + } + return true; + }); + if(param->change_callback) { + param->change_callback(param); + } +} + +void bt_test_process_ok(BtTest* bt_test) { + BtTestState state; + with_view_model( + bt_test->view, (BtTestModel * model) { + if(model->state == BtTestStateStarted) { + model->state = BtTestStateStopped; + model->message = BT_TEST_START_MESSAGE; + model->rssi = 0.0f; + model->packets_num_rx = 0; + model->packets_num_tx = 0; + } else if(model->state == BtTestStateStopped) { + model->state = BtTestStateStarted; + model->message = BT_TEST_STOP_MESSAGE; + } + state = model->state; + return true; + }); + if(bt_test->change_state_callback) { + bt_test->change_state_callback(state, bt_test->context); + } +} + +void bt_test_process_back(BtTest* bt_test) { + with_view_model( + bt_test->view, (BtTestModel * model) { + model->state = BtTestStateStopped; + model->rssi = 0.0f; + model->packets_num_rx = 0; + model->packets_num_tx = 0; + return false; + }); + if(bt_test->back_callback) { + bt_test->back_callback(bt_test->context); + } +} + +BtTest* bt_test_alloc() { + BtTest* bt_test = furi_alloc(sizeof(BtTest)); + bt_test->view = view_alloc(); + view_set_context(bt_test->view, bt_test); + view_allocate_model(bt_test->view, ViewModelTypeLocking, sizeof(BtTestModel)); + view_set_draw_callback(bt_test->view, bt_test_draw_callback); + view_set_input_callback(bt_test->view, bt_test_input_callback); + + with_view_model( + bt_test->view, (BtTestModel * model) { + model->state = BtTestStateStopped; + model->message = "Ok - Start"; + BtTestParamArray_init(model->params); + model->position = 0; + model->window_position = 0; + model->rssi = 0.0f; + model->packets_num_tx = 0; + model->packets_num_rx = 0; + return true; + }); + + return bt_test; +} + +void bt_test_free(BtTest* bt_test) { + furi_assert(bt_test); + + with_view_model( + bt_test->view, (BtTestModel * model) { + BtTestParamArray_it_t it; + for(BtTestParamArray_it(it, model->params); !BtTestParamArray_end_p(it); + BtTestParamArray_next(it)) { + string_clear(BtTestParamArray_ref(it)->current_value_text); + } + BtTestParamArray_clear(model->params); + return false; + }); + view_free(bt_test->view); + free(bt_test); +} + +View* bt_test_get_view(BtTest* bt_test) { + furi_assert(bt_test); + return bt_test->view; +} + +BtTestParam* bt_test_param_add( + BtTest* bt_test, + const char* label, + uint8_t values_count, + BtTestParamChangeCallback change_callback, + void* context) { + BtTestParam* param = NULL; + furi_assert(label); + furi_assert(bt_test); + + with_view_model( + bt_test->view, (BtTestModel * model) { + param = BtTestParamArray_push_new(model->params); + param->label = label; + param->values_count = values_count; + param->change_callback = change_callback; + param->context = context; + param->current_value_index = 0; + string_init(param->current_value_text); + return true; + }); + + return param; +} + +void bt_test_set_rssi(BtTest* bt_test, float rssi) { + furi_assert(bt_test); + with_view_model( + bt_test->view, (BtTestModel * model) { + model->rssi = rssi; + return true; + }); +} + +void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) { + furi_assert(bt_test); + with_view_model( + bt_test->view, (BtTestModel * model) { + model->packets_num_tx = packets_num; + return true; + }); +} + +void bt_test_set_packets_rx(BtTest* bt_test, uint32_t packets_num) { + furi_assert(bt_test); + with_view_model( + bt_test->view, (BtTestModel * model) { + model->packets_num_rx = packets_num; + return true; + }); +} + +void bt_test_set_change_state_callback(BtTest* bt_test, BtTestChangeStateCallback callback) { + furi_assert(bt_test); + furi_assert(callback); + bt_test->change_state_callback = callback; +} + +void bt_test_set_back_callback(BtTest* bt_test, BtTestBackCallback callback) { + furi_assert(bt_test); + furi_assert(callback); + bt_test->back_callback = callback; +} + +void bt_test_set_context(BtTest* bt_test, void* context) { + furi_assert(bt_test); + bt_test->context = context; +} + +void bt_test_set_current_value_index(BtTestParam* param, uint8_t current_value_index) { + param->current_value_index = current_value_index; +} + +void bt_test_set_current_value_text(BtTestParam* param, const char* current_value_text) { + string_set_str(param->current_value_text, current_value_text); +} + +uint8_t bt_test_get_current_value_index(BtTestParam* param) { + return param->current_value_index; +} + +void* bt_test_get_context(BtTestParam* param) { + return param->context; +} diff --git a/applications/bt/bt_debug_app/views/bt_test.h b/applications/bt/bt_debug_app/views/bt_test.h new file mode 100755 index 00000000..2d738cbd --- /dev/null +++ b/applications/bt/bt_debug_app/views/bt_test.h @@ -0,0 +1,46 @@ +#pragma once +#include + +typedef enum { + BtTestStateStarted, + BtTestStateStopped, +} BtTestState; + +typedef struct BtTest BtTest; +typedef void (*BtTestChangeStateCallback)(BtTestState state, void* context); +typedef void (*BtTestBackCallback)(void* context); +typedef struct BtTestParam BtTestParam; +typedef void (*BtTestParamChangeCallback)(BtTestParam* param); + +BtTest* bt_test_alloc(); + +void bt_test_free(BtTest* bt_test); + +View* bt_test_get_view(BtTest* bt_test); + +BtTestParam* bt_test_param_add( + BtTest* bt_test, + const char* label, + uint8_t values_count, + BtTestParamChangeCallback change_callback, + void* context); + +void bt_test_set_change_state_callback(BtTest* bt_test, BtTestChangeStateCallback callback); + +void bt_test_set_back_callback(BtTest* bt_test, BtTestBackCallback callback); + +void bt_test_set_context(BtTest* bt_test, void* context); + +void bt_test_set_rssi(BtTest* bt_test, float rssi); + +void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num); + +void bt_test_set_packets_rx(BtTest* bt_test, uint32_t packets_num); + +void bt_test_set_current_value_index(BtTestParam* param, uint8_t current_value_index); + +void bt_test_set_current_value_text(BtTestParam* param, const char* current_value_text); + +uint8_t bt_test_get_current_value_index(BtTestParam* param); + +void* bt_test_get_context(BtTestParam* param); diff --git a/applications/bt/bt_debug_app/views/bt_test_types.h b/applications/bt/bt_debug_app/views/bt_test_types.h new file mode 100644 index 00000000..433bb578 --- /dev/null +++ b/applications/bt/bt_debug_app/views/bt_test_types.h @@ -0,0 +1,30 @@ +#pragma once + +typedef enum { + BtTestModeRx, + BtTestModeTx, + BtTestModeTxHopping, +} BtTestMode; + +typedef enum { + BtTestChannel2402 = 0, + BtTestChannel2440 = 19, + BtTestChannel2480 = 39, +} BtTestChannel; + +typedef enum { + BtPower0dB = 0x19, + BtPower2dB = 0x1B, + BtPower4dB = 0x1D, + BtPower6dB = 0x1F, +} BtTestPower; + +typedef enum { + BtDataRate1M = 1, + BtDataRate2M = 2, +} BtTestDataRate; + +typedef struct { + uint32_t value; + const char* str; +} BtTestParamValue; diff --git a/applications/bt/bt_i.h b/applications/bt/bt_i.h deleted file mode 100644 index 6a5fe383..00000000 --- a/applications/bt/bt_i.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include "bt.h" -#include "bt_views.h" -#include "bt_types.h" - -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include - -struct Bt { - osMessageQueueId_t message_queue; - BtState state; - osTimerId_t update_status_timer; - osTimerId_t update_param_timer; - Gui* gui; - ValueMutex* menu; - // Status bar - ViewPort* statusbar_view_port; - // Menu - IconAnimation* menu_icon; - MenuItem* menu_item; - View* view_test_carrier; - View* view_test_packet_tx; - View* view_test_packet_rx; - View* view_start_app; - ViewDispatcher* view_dispatcher; -}; - -Bt* bt_alloc(); - -void bt_draw_statusbar_callback(Canvas* canvas, void* context); - -BtTestChannel bt_switch_channel(InputKey key, BtTestChannel inst_chan); - -void bt_draw_statusbar_callback(Canvas* canvas, void* context); - -void bt_menu_test_carrier(void* context); - -void bt_menu_test_packet_tx(void* context); - -void bt_menu_test_packet_rx(void* context); - -void bt_menu_start_app(void* context); diff --git a/applications/bt/bt_service/bt.c b/applications/bt/bt_service/bt.c new file mode 100644 index 00000000..76d4ae10 --- /dev/null +++ b/applications/bt/bt_service/bt.c @@ -0,0 +1,74 @@ +#include "bt_i.h" + +#define BT_SERVICE_TAG "BT" + +// static void bt_update_statusbar(void* arg) { +// furi_assert(arg); +// Bt* bt = arg; +// BtMessage m = {.type = BtMessageTypeUpdateStatusbar}; +// furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); +// } + +static void bt_draw_statusbar_callback(Canvas* canvas, void* context) { + canvas_draw_icon(canvas, 0, 0, &I_Bluetooth_5x8); +} + +static ViewPort* bt_statusbar_view_port_alloc() { + ViewPort* statusbar_view_port = view_port_alloc(); + view_port_set_width(statusbar_view_port, 5); + view_port_draw_callback_set(statusbar_view_port, bt_draw_statusbar_callback, NULL); + view_port_enabled_set(statusbar_view_port, false); + return statusbar_view_port; +} + +Bt* bt_alloc() { + Bt* bt = furi_alloc(sizeof(Bt)); + // Load settings + if(!bt_settings_load(&bt->bt_settings)) { + bt_settings_save(&bt->bt_settings); + } + // Alloc queue + bt->message_queue = osMessageQueueNew(8, sizeof(BtMessage), NULL); + + // doesn't make sense if we waiting for transition on service start + // bt->update_status_timer = osTimerNew(bt_update_statusbar, osTimerPeriodic, bt, NULL); + // osTimerStart(bt->update_status_timer, 4000); + + // Setup statusbar view port + bt->statusbar_view_port = bt_statusbar_view_port_alloc(); + // Gui + bt->gui = furi_record_open("gui"); + gui_add_view_port(bt->gui, bt->statusbar_view_port, GuiLayerStatusBarLeft); + + return bt; +} + +int32_t bt_srv() { + Bt* bt = bt_alloc(); + furi_record_create("bt", bt); + furi_hal_bt_init(); + + if(bt->bt_settings.enabled) { + if(!furi_hal_bt_wait_startup()) { + FURI_LOG_E(BT_SERVICE_TAG, "Core2 startup failed"); + } else { + view_port_enabled_set(bt->statusbar_view_port, true); + bool bt_app_started = furi_hal_bt_start_app(); + if(!bt_app_started) { + FURI_LOG_E(BT_SERVICE_TAG, "BT App start failed"); + } else { + FURI_LOG_I(BT_SERVICE_TAG, "BT App started"); + } + } + } + + BtMessage message; + while(1) { + furi_check(osMessageQueueGet(bt->message_queue, &message, NULL, osWaitForever) == osOK); + if(message.type == BtMessageTypeUpdateStatusbar) { + // Update statusbar + view_port_enabled_set(bt->statusbar_view_port, furi_hal_bt_is_alive()); + } + } + return 0; +} diff --git a/applications/bt/bt.h b/applications/bt/bt_service/bt.h similarity index 100% rename from applications/bt/bt.h rename to applications/bt/bt_service/bt.h diff --git a/applications/bt/bt_service/bt_i.h b/applications/bt/bt_service/bt_i.h new file mode 100644 index 00000000..b498e048 --- /dev/null +++ b/applications/bt/bt_service/bt_i.h @@ -0,0 +1,29 @@ +#pragma once + +#include "bt.h" + +#include +#include + +#include +#include +#include + +#include "../bt_settings.h" + +typedef enum { + BtMessageTypeUpdateStatusbar, +} BtMessageType; + +typedef struct { + BtMessageType type; + void* param; +} BtMessage; + +struct Bt { + BtSettings bt_settings; + osMessageQueueId_t message_queue; + osTimerId_t update_status_timer; + Gui* gui; + ViewPort* statusbar_view_port; +}; diff --git a/applications/bt/bt_settings.c b/applications/bt/bt_settings.c new file mode 100644 index 00000000..bd6399a9 --- /dev/null +++ b/applications/bt/bt_settings.c @@ -0,0 +1,50 @@ +#include "bt_settings.h" +#include +#include + +#define BT_SETTINGS_TAG "bt settings" +#define BT_SETTINGS_PATH "/int/bt.settings" + +bool bt_settings_load(BtSettings* bt_settings) { + furi_assert(bt_settings); + bool file_loaded = false; + BtSettings settings = {}; + + FURI_LOG_I(BT_SETTINGS_TAG, "Loading settings from \"%s\"", BT_SETTINGS_PATH); + FileWorker* file_worker = file_worker_alloc(true); + if(file_worker_open(file_worker, BT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { + if(file_worker_read(file_worker, &settings, sizeof(settings))) { + file_loaded = true; + } + } + file_worker_free(file_worker); + + if(file_loaded) { + FURI_LOG_I(BT_SETTINGS_TAG, "Settings load success"); + if(settings.version != BT_SETTINGS_VERSION) { + FURI_LOG_E(BT_SETTINGS_TAG, "Settings version mismatch"); + } else { + osKernelLock(); + *bt_settings = settings; + osKernelUnlock(); + } + } else { + FURI_LOG_E(BT_SETTINGS_TAG, "Settings load failed"); + } + return file_loaded; +} + +bool bt_settings_save(BtSettings* bt_settings) { + furi_assert(bt_settings); + bool result = false; + + FileWorker* file_worker = file_worker_alloc(true); + if(file_worker_open(file_worker, BT_SETTINGS_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) { + if(file_worker_write(file_worker, bt_settings, sizeof(BtSettings))) { + FURI_LOG_I(BT_SETTINGS_TAG, "Settings saved to \"%s\"", BT_SETTINGS_PATH); + result = true; + } + } + file_worker_free(file_worker); + return result; +} diff --git a/applications/bt/bt_settings.h b/applications/bt/bt_settings.h new file mode 100644 index 00000000..d0a539ea --- /dev/null +++ b/applications/bt/bt_settings.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#define BT_SETTINGS_VERSION (0) + +typedef struct { + uint8_t version; + bool enabled; +} BtSettings; + +bool bt_settings_load(BtSettings* bt_settings); + +bool bt_settings_save(BtSettings* bt_settings); diff --git a/applications/bt/bt_settings_app/bt_settings_app.c b/applications/bt/bt_settings_app/bt_settings_app.c new file mode 100755 index 00000000..6eaf3761 --- /dev/null +++ b/applications/bt/bt_settings_app/bt_settings_app.c @@ -0,0 +1,67 @@ +#include "bt_settings_app.h" + +static bool bt_settings_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + BtSettingsApp* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool bt_settings_back_event_callback(void* context) { + furi_assert(context); + BtSettingsApp* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +BtSettingsApp* bt_settings_app_alloc() { + BtSettingsApp* app = furi_alloc(sizeof(BtSettingsApp)); + + // Load settings + bt_settings_load(&app->settings); + app->gui = furi_record_open("gui"); + + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&bt_settings_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, bt_settings_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, bt_settings_back_event_callback); + + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + app->submenu = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, BtSettingsAppViewSubmenu, submenu_get_view(app->submenu)); + app->dialog_ex = dialog_ex_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, BtSettingsAppViewDialogEx, dialog_ex_get_view(app->dialog_ex)); + + scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneStart); + return app; +} + +void bt_settings_app_free(BtSettingsApp* app) { + furi_assert(app); + // Submenu + view_dispatcher_remove_view(app->view_dispatcher, BtSettingsAppViewSubmenu); + submenu_free(app->submenu); + // Dialog + view_dispatcher_remove_view(app->view_dispatcher, BtSettingsAppViewDialogEx); + dialog_ex_free(app->dialog_ex); + // View dispatcher + view_dispatcher_free(app->view_dispatcher); + scene_manager_free(app->scene_manager); + // Records + furi_record_close("gui"); + free(app); +} + +extern int32_t bt_settings_app(void* p) { + BtSettingsApp* app = bt_settings_app_alloc(); + view_dispatcher_run(app->view_dispatcher); + bt_settings_save(&app->settings); + bt_settings_app_free(app); + return 0; +} diff --git a/applications/bt/bt_settings_app/bt_settings_app.h b/applications/bt/bt_settings_app/bt_settings_app.h new file mode 100644 index 00000000..cfbea1d0 --- /dev/null +++ b/applications/bt/bt_settings_app/bt_settings_app.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include "../bt_settings.h" +#include "scenes/bt_settings_scene.h" + +typedef struct { + BtSettings settings; + Gui* gui; + SceneManager* scene_manager; + ViewDispatcher* view_dispatcher; + Submenu* submenu; + DialogEx* dialog_ex; +} BtSettingsApp; + +typedef enum { + BtSettingsAppViewSubmenu, + BtSettingsAppViewDialogEx, +} BtSettingsAppView; diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene.c new file mode 100644 index 00000000..cc1b1072 --- /dev/null +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene.c @@ -0,0 +1,30 @@ +#include "bt_settings_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const bt_settings_on_enter_handlers[])(void*) = { +#include "bt_settings_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const bt_settings_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "bt_settings_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const bt_settings_on_exit_handlers[])(void* context) = { +#include "bt_settings_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers bt_settings_scene_handlers = { + .on_enter_handlers = bt_settings_on_enter_handlers, + .on_event_handlers = bt_settings_on_event_handlers, + .on_exit_handlers = bt_settings_on_exit_handlers, + .scene_num = BtSettingsAppSceneNum, +}; diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene.h b/applications/bt/bt_settings_app/scenes/bt_settings_scene.h new file mode 100644 index 00000000..efe1c299 --- /dev/null +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) BtSettingsAppScene##id, +typedef enum { +#include "bt_settings_scene_config.h" + BtSettingsAppSceneNum, +} BtSettingsAppScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers bt_settings_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "bt_settings_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "bt_settings_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "bt_settings_scene_config.h" +#undef ADD_SCENE diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h b/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h new file mode 100644 index 00000000..e7d19b1a --- /dev/null +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h @@ -0,0 +1,2 @@ +ADD_SCENE(bt_settings, start, Start) +ADD_SCENE(bt_settings, disable_dialog, DisableDialog) diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_disable_dialog.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene_disable_dialog.c new file mode 100755 index 00000000..ac2d5f44 --- /dev/null +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene_disable_dialog.c @@ -0,0 +1,44 @@ +#include "../bt_settings_app.h" +#include +#include + +static void bt_setting_disable_dialog_callback(DialogExResult result, void* context) { + BtSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, result); +} + +void bt_settings_scene_disable_dialog_on_enter(void* context) { + BtSettingsApp* app = context; + DialogEx* dialog_ex = app->dialog_ex; + dialog_ex_set_text( + dialog_ex, "Reboot device\nto disable Bluetooth", 64, 32, AlignCenter, AlignCenter); + dialog_ex_set_left_button_text(dialog_ex, "Back"); + dialog_ex_set_right_button_text(dialog_ex, "Reboot"); + dialog_ex_set_result_callback(dialog_ex, bt_setting_disable_dialog_callback); + dialog_ex_set_context(dialog_ex, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, BtSettingsAppViewDialogEx); +} + +bool bt_settings_scene_disable_dialog_on_event(void* context, SceneManagerEvent event) { + BtSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == DialogExResultLeft) { + scene_manager_previous_scene(app->scene_manager); + consumed = true; + } else if(event.event == DialogExResultRight) { + app->settings.enabled = false; + bt_settings_save(&app->settings); + furi_hal_boot_set_mode(FuriHalBootModeNormal); + furi_hal_power_reset(); + } + } + return consumed; +} + +void bt_settings_scene_disable_dialog_on_exit(void* context) { + BtSettingsApp* app = context; + dialog_ex_clean(app->dialog_ex); +} diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c new file mode 100755 index 00000000..faf1d3a1 --- /dev/null +++ b/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c @@ -0,0 +1,56 @@ +#include "../bt_settings_app.h" +#include "furi-hal-bt.h" + +enum BtSettingsAppStartSubmenuIndex { + BtSettingsAppStartSubmenuIndexEnable, +}; + +static void bt_settings_scene_start_submenu_callback(void* context, uint32_t index) { + BtSettingsApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void bt_settings_scene_start_on_enter(void* context) { + BtSettingsApp* app = context; + Submenu* submenu = app->submenu; + + const char* submenu_label = app->settings.enabled ? "Disable" : "Enable"; + submenu_add_item( + submenu, + submenu_label, + BtSettingsAppStartSubmenuIndexEnable, + bt_settings_scene_start_submenu_callback, + app); + + view_dispatcher_switch_to_view(app->view_dispatcher, BtSettingsAppViewSubmenu); +} + +bool bt_settings_scene_start_on_event(void* context, SceneManagerEvent event) { + BtSettingsApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == BtSettingsAppStartSubmenuIndexEnable) { + if(!app->settings.enabled) { + app->settings.enabled = true; + furi_hal_bt_start_app(); + submenu_clean(app->submenu); + submenu_add_item( + app->submenu, + "Disable", + BtSettingsAppStartSubmenuIndexEnable, + bt_settings_scene_start_submenu_callback, + app); + } else { + scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneDisableDialog); + } + consumed = true; + } + } + return consumed; +} + +void bt_settings_scene_start_on_exit(void* context) { + BtSettingsApp* app = context; + submenu_clean(app->submenu); +} diff --git a/applications/bt/bt_types.h b/applications/bt/bt_types.h deleted file mode 100644 index 4cff4105..00000000 --- a/applications/bt/bt_types.h +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include - -typedef enum { - BtMessageTypeStartTestCarrier, - BtMessageTypeHoppingTx, - BtMessageTypeStopTestCarrier, - BtMessageTypeSetupTestPacketTx, - BtMessageTypeSetupTestPacketRx, - BtMessageTypeStartTestPacketTx, - BtMessageTypeStartTestPacketRx, - BtMessageTypeStopTestPacket, - BtMessageTypeStartApp, - BtMessageTypeUpdateStatusbar, -} BtMessageType; - -typedef enum { - BtStateReady, - BtStateCarrierTx, - BtStateHoppingTx, - BtStateCarrierRxStart, - BtStateCarrierRxRunning, - BtStatePacketSetup, - BtStatePacketStart, - BtStatePacketRunning, - BtStateStartedApp, -} BtStateType; - -typedef enum { - BtChannel2402 = 0, - BtChannel2440 = 19, - BtChannel2480 = 39, -} BtTestChannel; - -typedef enum { - BtPower0dB = 0x19, - BtPower2dB = 0x1B, - BtPower4dB = 0x1D, - BtPower6dB = 0x1F, -} BtTestPower; - -typedef enum { - BtDataRate1M = 1, - BtDataRate2M = 2, -} BtTestDataRate; - -typedef struct { - BtTestChannel channel; - BtTestPower power; - BtTestDataRate datarate; - float rssi; - uint16_t packets_sent; - uint16_t packets_received; -} BtTestParam; - -typedef struct { - BtMessageType type; - BtTestParam param; -} BtMessage; - -typedef struct { - BtStateType type; - BtTestParam param; -} BtState; diff --git a/applications/bt/bt_views.c b/applications/bt/bt_views.c deleted file mode 100755 index fc55c169..00000000 --- a/applications/bt/bt_views.c +++ /dev/null @@ -1,250 +0,0 @@ -#include "bt_views.h" - -void bt_view_test_carrier_draw(Canvas* canvas, void* model) { - BtViewTestCarrierModel* m = model; - canvas_clear(canvas); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 0, 12, "Performing Carrier test"); - if(m->type == BtStateCarrierTx) { - canvas_draw_str(canvas, 0, 24, "Manual Carrier TX"); - } else if(m->type == BtStateHoppingTx) { - canvas_draw_str(canvas, 0, 24, "Carrier TX Hopping mode"); - } else if(m->type == BtStateCarrierRxRunning) { - canvas_draw_str(canvas, 0, 24, "Manual Carrier RX"); - } - char buffer[32]; - snprintf(buffer, sizeof(buffer), "Channel:%d MHz", m->channel * 2 + 2402); - canvas_draw_str(canvas, 0, 36, buffer); - if(m->type == BtStateCarrierTx || m->type == BtStateHoppingTx) { - snprintf(buffer, sizeof(buffer), "Power:%d dB", m->power - BtPower0dB); - } else if(m->type == BtStateCarrierRxRunning) { - snprintf(buffer, sizeof(buffer), "RSSI: %3.1f dB", m->rssi); - } - canvas_draw_str(canvas, 0, 48, buffer); -} - -void bt_view_test_packet_rx_draw(Canvas* canvas, void* model) { - BtViewTestPacketRxModel* m = model; - canvas_clear(canvas); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 0, 12, "Performing packets RX test"); - if(m->type == BtStatePacketSetup) { - canvas_draw_str(canvas, 0, 24, "Setup parameters. Ok to start"); - } else { - canvas_draw_str(canvas, 0, 24, "Receiving packets ..."); - } - char buffer[32]; - snprintf(buffer, sizeof(buffer), "Channel:%d MHz", m->channel * 2 + 2402); - canvas_draw_str(canvas, 0, 36, buffer); - snprintf(buffer, sizeof(buffer), "Datarate:%d Mbps", m->datarate); - canvas_draw_str(canvas, 0, 48, buffer); - if(m->type == BtStatePacketSetup) { - snprintf(buffer, sizeof(buffer), "%d packets received", m->packets_received); - } else { - snprintf(buffer, sizeof(buffer), "RSSI: %3.1f dB", m->rssi); - } - canvas_draw_str(canvas, 0, 60, buffer); -} - -void bt_view_test_packet_tx_draw(Canvas* canvas, void* model) { - BtViewTestPacketTxModel* m = model; - canvas_clear(canvas); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 0, 12, "Packets send TX test"); - if(m->type == BtStatePacketSetup) { - canvas_draw_str(canvas, 0, 24, "Setup parameters. Ok to start"); - } else { - canvas_draw_str(canvas, 0, 24, "Sending packets ..."); - } - char buffer[32]; - snprintf(buffer, sizeof(buffer), "Channel:%d MHz", m->channel * 2 + 2402); - canvas_draw_str(canvas, 0, 36, buffer); - snprintf(buffer, sizeof(buffer), "Datarate:%d Mbps", m->datarate); - canvas_draw_str(canvas, 0, 48, buffer); - if(m->packets_sent && m->type == BtStatePacketSetup) { - snprintf(buffer, sizeof(buffer), "%d packets sent", m->packets_sent); - canvas_draw_str(canvas, 0, 60, buffer); - } -} - -void bt_view_app_draw(Canvas* canvas, void* model) { - canvas_clear(canvas); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 0, 12, "Start BLE app"); -} - -BtTestChannel bt_switch_channel(InputKey key, BtTestChannel inst_chan) { - uint8_t pos = 0; - BtTestChannel arr[] = {BtChannel2402, BtChannel2440, BtChannel2480}; - for(pos = 0; pos < sizeof(arr); pos++) { - if(arr[pos] == inst_chan) { - break; - } - } - if(key == InputKeyRight) { - pos = (pos + 1) % sizeof(arr); - return arr[pos]; - } else if(key == InputKeyLeft) { - if(pos) { - return arr[pos - 1]; - } else { - return arr[sizeof(arr) - 1]; - } - } - return arr[0]; -} - -bool bt_view_test_carrier_input(InputEvent* event, void* context) { - furi_assert(event); - furi_assert(context); - Bt* bt = context; - if(event->type == InputTypeShort) { - if(event->key == InputKeyBack) { - if(osTimerIsRunning(bt->update_param_timer)) { - osTimerStop(bt->update_param_timer); - } - BtMessage m = {.type = BtMessageTypeStopTestCarrier}; - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); - view_dispatcher_switch_to_view(bt->view_dispatcher, VIEW_NONE); - return true; - } else { - if(event->key == InputKeyRight || event->key == InputKeyLeft) { - bt->state.param.channel = bt_switch_channel(event->key, bt->state.param.channel); - } else if(event->key == InputKeyUp) { - if(bt->state.param.power < BtPower6dB) { - bt->state.param.power += 2; - } - } else if(event->key == InputKeyDown) { - if(bt->state.param.power > BtPower0dB) { - bt->state.param.power -= 2; - } - } else if(event->key == InputKeyOk) { - if(bt->state.type == BtStateCarrierTx) { - bt->state.type = BtStateHoppingTx; - osTimerStart(bt->update_param_timer, 2000); - } else if(bt->state.type == BtStateHoppingTx) { - osTimerStop(bt->update_param_timer); - bt->state.type = BtStateCarrierRxStart; - osTimerStart(bt->update_param_timer, 200); - } else { - osTimerStop(bt->update_param_timer); - bt->state.type = BtStateCarrierTx; - } - } - BtMessage m = { - .type = BtMessageTypeStartTestCarrier, - .param.channel = bt->state.param.channel, - .param.power = bt->state.param.power}; - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); - return true; - } - } - return false; -} - -bool bt_view_test_packet_tx_input(InputEvent* event, void* context) { - furi_assert(event); - furi_assert(context); - Bt* bt = context; - if(event->type == InputTypeShort) { - if(event->key < InputKeyOk) { - // Process InputKeyUp, InputKeyDown, InputKeyLeft, InputKeyRight - if(event->key == InputKeyRight || event->key == InputKeyLeft) { - bt->state.param.channel = bt_switch_channel(event->key, bt->state.param.channel); - } else if(event->key == InputKeyUp) { - if(bt->state.param.datarate < BtDataRate2M) { - bt->state.param.datarate += 1; - } - } else if(event->key == InputKeyDown) { - if(bt->state.param.datarate > BtDataRate1M) { - bt->state.param.datarate -= 1; - } - } - bt->state.type = BtStatePacketSetup; - BtMessage m = { - .type = BtMessageTypeSetupTestPacketTx, - .param.channel = bt->state.param.channel, - .param.datarate = bt->state.param.datarate, - }; - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); - return true; - } else if(event->key == InputKeyOk) { - if(bt->state.type == BtStatePacketSetup) { - bt->state.type = BtStatePacketStart; - } else if(bt->state.type == BtStatePacketStart) { - bt->state.type = BtStatePacketSetup; - } - BtMessage m = { - .type = BtMessageTypeStartTestPacketTx, - .param.channel = bt->state.param.channel, - .param.datarate = bt->state.param.datarate, - }; - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); - return true; - } else if(event->key == InputKeyBack) { - BtMessage m = { - .type = BtMessageTypeStopTestPacket, - }; - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); - view_dispatcher_switch_to_view(bt->view_dispatcher, VIEW_NONE); - return true; - } - } - return false; -} - -bool bt_view_test_packet_rx_input(InputEvent* event, void* context) { - furi_assert(event); - furi_assert(context); - Bt* bt = context; - if(event->type == InputTypeShort) { - if(event->key < InputKeyOk) { - // Process InputKeyUp, InputKeyDown, InputKeyLeft, InputKeyRight - if(event->key == InputKeyRight || event->key == InputKeyLeft) { - bt->state.param.channel = bt_switch_channel(event->key, bt->state.param.channel); - } else if(event->key == InputKeyUp) { - if(bt->state.param.datarate < BtDataRate2M) { - bt->state.param.datarate += 1; - } - } else if(event->key == InputKeyDown) { - if(bt->state.param.datarate > BtDataRate1M) { - bt->state.param.datarate -= 1; - } - } - bt->state.type = BtStatePacketSetup; - BtMessage m = { - .type = BtMessageTypeSetupTestPacketRx, - .param.channel = bt->state.param.channel, - .param.datarate = bt->state.param.datarate, - }; - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); - return true; - } else if(event->key == InputKeyOk) { - if(bt->state.type == BtStatePacketSetup) { - bt->state.type = BtStatePacketStart; - osTimerStart(bt->update_param_timer, 200); - } else if(bt->state.type == BtStatePacketRunning) { - bt->state.type = BtStatePacketSetup; - osTimerStop(bt->update_param_timer); - } - BtMessage m = { - .type = BtMessageTypeStartTestPacketRx, - .param.channel = bt->state.param.channel, - .param.datarate = bt->state.param.datarate, - }; - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); - return true; - } else if(event->key == InputKeyBack) { - if(osTimerIsRunning(bt->update_param_timer)) { - osTimerStop(bt->update_param_timer); - } - BtMessage m = { - .type = BtMessageTypeStopTestPacket, - }; - furi_check(osMessageQueuePut(bt->message_queue, &m, 0, osWaitForever) == osOK); - view_dispatcher_switch_to_view(bt->view_dispatcher, VIEW_NONE); - return true; - } - } - return false; -} diff --git a/applications/bt/bt_views.h b/applications/bt/bt_views.h deleted file mode 100644 index 9103f18f..00000000 --- a/applications/bt/bt_views.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "bt_i.h" -#include "bt_types.h" - -#include -#include -#include -#include -#include -#include - -typedef enum { - BtViewTestCarrier, - BtViewTestPacketTx, - BtViewTestPacketRx, - BtViewStartApp, -} BtView; - -typedef struct { - BtStateType type; - BtTestChannel channel; - BtTestPower power; - float rssi; -} BtViewTestCarrierModel; - -typedef struct { - BtStateType type; - BtTestChannel channel; - BtTestDataRate datarate; - uint16_t packets_sent; -} BtViewTestPacketTxModel; - -typedef struct { - BtStateType type; - BtTestChannel channel; - BtTestDataRate datarate; - float rssi; - uint16_t packets_received; -} BtViewTestPacketRxModel; - -void bt_view_test_carrier_draw(Canvas* canvas, void* model); - -bool bt_view_test_carrier_input(InputEvent* event, void* context); - -void bt_view_test_packet_tx_draw(Canvas* canvas, void* model); - -bool bt_view_test_packet_tx_input(InputEvent* event, void* context); - -void bt_view_test_packet_rx_draw(Canvas* canvas, void* model); - -bool bt_view_test_packet_rx_input(InputEvent* event, void* context); - -void bt_view_app_draw(Canvas* canvas, void* model); diff --git a/applications/gui/modules/dialog_ex.c b/applications/gui/modules/dialog_ex.c old mode 100644 new mode 100755 index 9a758983..71375030 --- a/applications/gui/modules/dialog_ex.c +++ b/applications/gui/modules/dialog_ex.c @@ -243,3 +243,22 @@ void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text) { return true; }); } + +void dialog_ex_clean(DialogEx* dialog_ex) { + furi_assert(dialog_ex); + TextElement clean_text_el = { + .text = NULL, .x = 0, .y = 0, .horizontal = AlignLeft, .vertical = AlignLeft}; + IconElement clean_icon_el = {.icon = NULL, .x = 0, .y = 0}; + with_view_model( + dialog_ex->view, (DialogExModel * model) { + model->header = clean_text_el; + model->text = clean_text_el; + model->icon = clean_icon_el; + model->left_text = NULL; + model->center_text = NULL; + model->right_text = NULL; + return true; + }); + dialog_ex->context = NULL; + dialog_ex->callback = NULL; +} diff --git a/applications/gui/modules/dialog_ex.h b/applications/gui/modules/dialog_ex.h index b80fbcb0..7833128a 100644 --- a/applications/gui/modules/dialog_ex.h +++ b/applications/gui/modules/dialog_ex.h @@ -5,50 +5,51 @@ extern "C" { #endif -/* Dialog anonymous structure */ +/** Dialog anonymous structure */ typedef struct DialogEx DialogEx; -/* DialogEx result */ +/** DialogEx result */ typedef enum { DialogExResultLeft, DialogExResultCenter, DialogExResultRight, } DialogExResult; -/* DialogEx result callback type +/** DialogEx result callback type * @warning comes from GUI thread */ typedef void (*DialogExResultCallback)(DialogExResult result, void* context); -/* Allocate and initialize dialog - * This dialog used to ask simple questions like Yes/ +/** Allocate and initialize dialog + * This dialog used to ask simple questions + * @return DialogEx instance */ DialogEx* dialog_ex_alloc(); -/* Deinitialize and free dialog +/** Deinitialize and free dialog * @param dialog - DialogEx instance */ void dialog_ex_free(DialogEx* dialog_ex); -/* Get dialog view +/** Get dialog view * @param dialog - DialogEx instance * @return View instance that can be used for embedding */ View* dialog_ex_get_view(DialogEx* dialog_ex); -/* Set dialog result callback +/** Set dialog result callback * @param dialog_ex - DialogEx instance * @param callback - result callback function */ void dialog_ex_set_result_callback(DialogEx* dialog_ex, DialogExResultCallback callback); -/* Set dialog context +/** Set dialog context * @param dialog_ex - DialogEx instance * @param context - context pointer, will be passed to result callback */ void dialog_ex_set_context(DialogEx* dialog_ex, void* context); -/* Set dialog header text +/** Set dialog header text * If text is null, dialog header will not be rendered * @param dialog - DialogEx instance * @param text - text to be shown, can be multiline @@ -63,7 +64,7 @@ void dialog_ex_set_header( Align horizontal, Align vertical); -/* Set dialog text +/** Set dialog text * If text is null, dialog text will not be rendered * @param dialog - DialogEx instance * @param text - text to be shown, can be multiline @@ -78,7 +79,7 @@ void dialog_ex_set_text( Align horizontal, Align vertical); -/* Set dialog icon +/** Set dialog icon * If x or y is negative, dialog icon will not be rendered * @param dialog - DialogEx instance * @param x, y - icon position @@ -86,27 +87,32 @@ void dialog_ex_set_text( */ void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, const Icon* icon); -/* Set left button text +/** Set left button text * If text is null, left button will not be rendered and processed * @param dialog - DialogEx instance * @param text - text to be shown */ void dialog_ex_set_left_button_text(DialogEx* dialog_ex, const char* text); -/* Set center button text +/** Set center button text * If text is null, center button will not be rendered and processed * @param dialog - DialogEx instance * @param text - text to be shown */ void dialog_ex_set_center_button_text(DialogEx* dialog_ex, const char* text); -/* Set right button text +/** Set right button text * If text is null, right button will not be rendered and processed * @param dialog - DialogEx instance * @param text - text to be shown */ void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text); +/** Clean dialog + * @param dialog_ex DialogEx instance + */ +void dialog_ex_clean(DialogEx* dialog_ex); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/applications/loader/loader.c b/applications/loader/loader.c index 50630ac6..0ef11677 100644 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -238,7 +238,7 @@ static void loader_build_menu() { with_value_mutex( loader_instance->menu_vm, (Menu * menu) { MenuItem* menu_debug = - menu_item_alloc_menu("Debug tools", icon_animation_alloc(&A_Settings_14)); + menu_item_alloc_menu("Debug tools", icon_animation_alloc(&A_Debug_14)); for(size_t i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) { // Add menu item diff --git a/assets/compiled/assets_icons.c b/assets/compiled/assets_icons.c index f95f04c1..60282caf 100644 --- a/assets/compiled/assets_icons.c +++ b/assets/compiled/assets_icons.c @@ -98,18 +98,6 @@ const uint8_t *_I_Flipper_young_80x60[] = {_I_Flipper_young_80x60_0}; const uint8_t _I_DolphinFirstStart3_57x48_0[] = {0x00,0x00,0x00,0x80,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x04,0x00,0x00,0xF8,0x03,0x01,0x00,0x00,0x08,0x00,0x00,0x04,0xBC,0x00,0x00,0x00,0x10,0x00,0x00,0x02,0xC0,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x02,0x00,0x38,0x40,0x00,0x00,0x02,0x00,0x04,0x00,0x3E,0x40,0x00,0x00,0xF4,0x03,0x08,0x80,0x07,0x80,0x00,0x00,0x5C,0x0D,0x10,0xE0,0x01,0x80,0x00,0x00,0xA8,0x3A,0x20,0xE0,0x00,0x00,0x01,0x00,0x58,0x55,0x00,0xC0,0x01,0x00,0x01,0x00,0xB0,0xAA,0x00,0x80,0x07,0x00,0x01,0x00,0x60,0x55,0x01,0x00,0x1E,0x00,0x01,0x0E,0xC0,0xAA,0x02,0xE0,0x5C,0x00,0x01,0x11,0x80,0x55,0x05,0x00,0xA9,0x00,0x01,0x21,0x00,0xAB,0x0A,0x00,0x56,0x07,0x01,0x41,0x00,0x56,0x15,0x00,0xEC,0x08,0x01,0x81,0x00,0xBF,0x2A,0x00,0x34,0x08,0x01,0x01,0xF1,0xC0,0x57,0x00,0x0C,0x08,0x01,0x02,0x0A,0x00,0xBE,0x00,0x04,0x08,0x01,0x02,0x06,0x00,0x78,0x83,0x02,0x04,0x01,0x02,0x0C,0x00,0xF0,0x7F,0x01,0x04,0x01,0x02,0xF4,0x01,0xFE,0x81,0x00,0x04,0x01,0x04,0x08,0xFF,0x6B,0x40,0x00,0x02,0x01,0x04,0x88,0x55,0x1D,0x40,0x00,0x02,0x01,0x04,0x50,0xAA,0x06,0x20,0x00,0x02,0x01,0x04,0x30,0xD4,0x01,0x20,0x00,0x01,0x01,0x04,0x10,0x68,0x00,0x10,0x00,0x01,0x01,0x04,0x18,0x18,0x00,0x10,0x00,0x01,0x01,0x08,0x18,0x06,0x80,0x10,0x00,0x01,0x01,0x08,0xE8,0x01,0x60,0x08,0x80,0x00,0x01,0x08,0x08,0x00,0x18,0x08,0x80,0x00,0x00,0x08,0x10,0x00,0x06,0x08,0x80,0x00,0x00,0x08,0x60,0xE0,0x01,0x08,0x80,0x00,0x00,0x08,0x80,0x1F,0x00,0x08,0x80,0x00,0x00,0x08,0x80,0x04,0x00,0x04,0x00,0x01,0x00,0x08,0x80,0x04,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x01,0x00,0x04,0x00,0x02,0x00,0x10,0x00,0x01,0x00,0x04,0x00,0x02,0x00,0x10,0x80,0x00,0x00,0x04,0x00,0x02,0x00,0x10,0x80,0x00,0x00,0x04,0x00,0x06,0x00,}; const uint8_t *_I_DolphinFirstStart3_57x48[] = {_I_DolphinFirstStart3_57x48_0}; -const uint8_t _I_Scanning_123x52_0[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x07,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0x03,0x18,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x56,0x05,0x60,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x81,0x0A,0x80,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x80,0x00,0x15,0x00,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x40,0x00,0x38,0x00,0x02,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x20,0x00,0x74,0x00,0x04,0x00,0x00,0x40,0x82,0x01,0x00,0x00,0x00,0x41,0x00,0x00,0x20,0x00,0x68,0x00,0x04,0x00,0x00,0x20,0x82,0x02,0x06,0x00,0x00,0x21,0x00,0x00,0x10,0x00,0xD0,0xE0,0x0F,0x00,0x00,0x20,0x82,0x02,0x0A,0x0C,0x80,0x20,0x08,0x00,0x10,0x00,0xA0,0x1C,0x10,0x00,0x00,0x20,0x82,0x02,0x0A,0x14,0x80,0x10,0x04,0x00,0x08,0xE0,0xD3,0x03,0x10,0x00,0x00,0x10,0x82,0x02,0x0A,0x14,0x80,0x10,0x02,0x00,0x08,0x90,0xA7,0x40,0x24,0x00,0x00,0x10,0x82,0x02,0x0A,0x14,0x80,0x10,0x02,0x00,0x08,0xC8,0x7F,0x84,0x28,0x00,0x00,0x10,0x84,0x02,0x0A,0xFF,0x80,0x10,0x02,0x00,0x88,0x67,0x3E,0x88,0x28,0x00,0x00,0x10,0x84,0xFA,0xFF,0xFF,0x80,0x10,0x02,0x00,0x44,0x64,0x2E,0x88,0x28,0x00,0x00,0x10,0xFC,0xAF,0xFF,0x15,0x80,0x10,0x04,0x00,0x44,0xE4,0x2F,0x88,0x2A,0x00,0x00,0x18,0xD4,0xDF,0x1F,0x14,0x80,0x20,0x08,0x00,0x44,0xE4,0x2F,0x50,0xFF,0x00,0xFE,0x1F,0xEC,0x3F,0x0A,0x14,0x00,0x21,0x00,0x00,0x44,0xC4,0x2F,0xEA,0x00,0x01,0x01,0x1A,0xFC,0x02,0x0A,0x14,0x00,0x41,0x00,0x00,0x84,0x88,0x2F,0x1D,0x00,0x82,0x7D,0x1E,0x84,0x02,0x0A,0x18,0x00,0x82,0x00,0x00,0x86,0x1F,0xC6,0x06,0x00,0x84,0x7D,0x16,0x84,0x02,0x0A,0x00,0x00,0x02,0x00,0x00,0x46,0xF5,0xC3,0x01,0x00,0x44,0x01,0x22,0x84,0x02,0x0C,0x00,0x00,0x04,0x00,0x00,0x87,0x0A,0x7C,0x00,0x00,0x44,0x03,0x22,0x88,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x45,0x05,0x08,0x00,0x7E,0xA4,0x03,0x42,0x88,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x86,0x06,0x00,0xC0,0x81,0xA5,0x07,0x42,0x08,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x30,0x00,0xD2,0xFF,0x81,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x0C,0x00,0xD2,0x1F,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x80,0x00,0x03,0x00,0xD1,0x1F,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xE1,0x00,0x80,0xE9,0x0F,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x1E,0x00,0xC0,0xE8,0x0F,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x70,0xEE,0x0F,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3C,0xF9,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xAA,0x9F,0xF0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x55,0xFD,0x5F,0xF0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0xEA,0xFF,0x3F,0xE0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0xD5,0xFF,0x1F,0xE0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x80,0xAA,0xFF,0x0F,0xE0,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x55,0x55,0x03,0xF0,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xAA,0xAA,0x00,0xB0,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x54,0x75,0x00,0x58,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xA8,0x0F,0x00,0xA8,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x7C,0x00,0x00,0x5C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0xAE,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0xD7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x80,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0xC0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; -const uint8_t *_I_Scanning_123x52[] = {_I_Scanning_123x52_0}; - -const uint8_t _I_Quest_7x8_0[] = {0x1E,0x33,0x33,0x30,0x18,0x0C,0x00,0x0C,}; -const uint8_t *_I_Quest_7x8[] = {_I_Quest_7x8_0}; - -const uint8_t _I_Unlock_7x8_0[] = {0x1C,0x22,0x02,0x4F,0x67,0x73,0x79,0x3C,}; -const uint8_t *_I_Unlock_7x8[] = {_I_Unlock_7x8_0}; - -const uint8_t _I_Lock_7x8_0[] = {0x1C,0x22,0x22,0x7F,0x7F,0x77,0x7F,0x3E,}; -const uint8_t *_I_Lock_7x8[] = {_I_Lock_7x8_0}; - const uint8_t _I_PassportBottom_128x17_0[] = {0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0xF9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0D,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x05,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x05,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x09,0x79,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xD5,0x80,0x55,0xD5,0x00,0xF3,0xCC,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x6A,0x00,0xAB,0x6A,0x00,0x06,0x86,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0xFE,0x3F,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; const uint8_t *_I_PassportBottom_128x17[] = {_I_PassportBottom_128x17_0}; @@ -220,6 +208,12 @@ const uint8_t _A_Bluetooth_14_4[] = {0x10,0x00,0x30,0x00,0x51,0x00,0x92,0x00,0x9 const uint8_t _A_Bluetooth_14_5[] = {0x10,0x00,0x30,0x00,0x51,0x00,0x92,0x00,0x94,0x04,0x58,0x08,0x30,0x09,0x30,0x09,0x58,0x08,0x94,0x04,0x92,0x00,0x51,0x00,0x30,0x00,0x10,0x00,}; const uint8_t *_A_Bluetooth_14[] = {_A_Bluetooth_14_0,_A_Bluetooth_14_1,_A_Bluetooth_14_2,_A_Bluetooth_14_3,_A_Bluetooth_14_4,_A_Bluetooth_14_5}; +const uint8_t _A_Debug_14_0[] = {0x20,0x01,0xC1,0x20,0x22,0x11,0x24,0x09,0xD9,0x26,0x16,0x1A,0xD8,0x06,0xD8,0x06,0xD6,0x1A,0x19,0x26,0xE4,0x09,0xC2,0x10,0x01,0x20,0x00,0x00,}; +const uint8_t _A_Debug_14_1[] = {0x20,0x01,0xC0,0x00,0x22,0x11,0x25,0x29,0xD8,0x06,0x16,0x1A,0xD9,0x26,0xD8,0x06,0xD4,0x0A,0x12,0x12,0xEA,0x15,0xC5,0x28,0x02,0x10,0x02,0x10,}; +const uint8_t _A_Debug_14_2[] = {0x20,0x01,0xC0,0x00,0x20,0x01,0x24,0x09,0xDA,0x16,0x11,0x22,0xDC,0x0E,0xDA,0x16,0xD9,0x26,0x14,0x0A,0xF2,0x13,0xD1,0x22,0x08,0x04,0x06,0x18,}; +const uint8_t _A_Debug_14_3[] = {0x22,0x11,0xC4,0x08,0x24,0x09,0x25,0x29,0xD9,0x26,0x12,0x12,0xDC,0x0E,0xD8,0x06,0xD8,0x06,0x14,0x0A,0xF4,0x0B,0xD2,0x12,0x19,0x26,0x06,0x18,}; +const uint8_t *_A_Debug_14[] = {_A_Debug_14_0,_A_Debug_14_1,_A_Debug_14_2,_A_Debug_14_3}; + const uint8_t _A_FileManager_14_0[] = {0xFC,0x07,0x04,0x04,0xF4,0x05,0x04,0x04,0xF7,0x05,0x05,0x04,0xF5,0x3F,0x15,0x20,0x0D,0x20,0x0D,0x10,0x05,0x10,0x05,0x08,0x03,0x08,0xFE,0x07,}; const uint8_t _A_FileManager_14_1[] = {0x00,0x00,0x00,0x00,0xFC,0x07,0x04,0x04,0xF7,0x05,0x05,0x04,0xF5,0x3F,0x15,0x20,0x0D,0x20,0x0D,0x10,0x05,0x10,0x05,0x08,0x03,0x08,0xFE,0x07,}; const uint8_t _A_FileManager_14_2[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x07,0x05,0x04,0xF5,0x3F,0x15,0x20,0x0D,0x20,0x0D,0x10,0x05,0x10,0x05,0x08,0x03,0x08,0xFE,0x07,}; @@ -423,6 +417,18 @@ const uint8_t *_I_Bluetooth_5x8[] = {_I_Bluetooth_5x8_0}; const uint8_t _I_Background_128x11_0[] = {0xFE,0x01,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x7D,0x06,0x00,0x00,0x00,0x00,0x00,0x18,0xFF,0xB7,0x55,0x31,0x00,0x00,0x00,0x00,0x81,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x00,0x00,0x00,0xE2,0xFF,0xFF,0xFF,0x7F,0x3D,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0xB6,0xEA,0xFF,0x04,0x00,0x00,0x00,0x80,0x41,0xFE,0xFF,0xFF,0xAA,0xFE,0xFF,0x3F,0x01,0x00,0x00,0xF9,0xFF,0xFF,0xFF,0xAB,0x9F,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF8,0xFF,0x7F,0x02,0x00,0x00,0x00,0x80,0x3E,0xFF,0xFF,0xFF,0xFF,0x55,0xFD,0x7F,0xFC,0xFF,0xFF,0x6C,0xFF,0xFF,0xFF,0xB5,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x80,0x01,0x00,0x00,0x00,0x80,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0xFE,0xFF,0xFF,0xFF,0x7F,}; const uint8_t *_I_Background_128x11[] = {_I_Background_128x11_0}; +const uint8_t _I_Scanning_123x52_0[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x07,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0x03,0x18,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x56,0x05,0x60,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x81,0x0A,0x80,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x80,0x00,0x15,0x00,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x40,0x00,0x38,0x00,0x02,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x20,0x00,0x74,0x00,0x04,0x00,0x00,0x40,0x82,0x01,0x00,0x00,0x00,0x41,0x00,0x00,0x20,0x00,0x68,0x00,0x04,0x00,0x00,0x20,0x82,0x02,0x06,0x00,0x00,0x21,0x00,0x00,0x10,0x00,0xD0,0xE0,0x0F,0x00,0x00,0x20,0x82,0x02,0x0A,0x0C,0x80,0x20,0x08,0x00,0x10,0x00,0xA0,0x1C,0x10,0x00,0x00,0x20,0x82,0x02,0x0A,0x14,0x80,0x10,0x04,0x00,0x08,0xE0,0xD3,0x03,0x10,0x00,0x00,0x10,0x82,0x02,0x0A,0x14,0x80,0x10,0x02,0x00,0x08,0x90,0xA7,0x40,0x24,0x00,0x00,0x10,0x82,0x02,0x0A,0x14,0x80,0x10,0x02,0x00,0x08,0xC8,0x7F,0x84,0x28,0x00,0x00,0x10,0x84,0x02,0x0A,0xFF,0x80,0x10,0x02,0x00,0x88,0x67,0x3E,0x88,0x28,0x00,0x00,0x10,0x84,0xFA,0xFF,0xFF,0x80,0x10,0x02,0x00,0x44,0x64,0x2E,0x88,0x28,0x00,0x00,0x10,0xFC,0xAF,0xFF,0x15,0x80,0x10,0x04,0x00,0x44,0xE4,0x2F,0x88,0x2A,0x00,0x00,0x18,0xD4,0xDF,0x1F,0x14,0x80,0x20,0x08,0x00,0x44,0xE4,0x2F,0x50,0xFF,0x00,0xFE,0x1F,0xEC,0x3F,0x0A,0x14,0x00,0x21,0x00,0x00,0x44,0xC4,0x2F,0xEA,0x00,0x01,0x01,0x1A,0xFC,0x02,0x0A,0x14,0x00,0x41,0x00,0x00,0x84,0x88,0x2F,0x1D,0x00,0x82,0x7D,0x1E,0x84,0x02,0x0A,0x18,0x00,0x82,0x00,0x00,0x86,0x1F,0xC6,0x06,0x00,0x84,0x7D,0x16,0x84,0x02,0x0A,0x00,0x00,0x02,0x00,0x00,0x46,0xF5,0xC3,0x01,0x00,0x44,0x01,0x22,0x84,0x02,0x0C,0x00,0x00,0x04,0x00,0x00,0x87,0x0A,0x7C,0x00,0x00,0x44,0x03,0x22,0x88,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x45,0x05,0x08,0x00,0x7E,0xA4,0x03,0x42,0x88,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x86,0x06,0x00,0xC0,0x81,0xA5,0x07,0x42,0x08,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x30,0x00,0xD2,0xFF,0x81,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x0C,0x00,0xD2,0x1F,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x80,0x00,0x03,0x00,0xD1,0x1F,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xE1,0x00,0x80,0xE9,0x0F,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x1E,0x00,0xC0,0xE8,0x0F,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x70,0xEE,0x0F,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3C,0xF9,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xAA,0x9F,0xF0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x55,0xFD,0x5F,0xF0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0xEA,0xFF,0x3F,0xE0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0xD5,0xFF,0x1F,0xE0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x80,0xAA,0xFF,0x0F,0xE0,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x55,0x55,0x03,0xF0,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xAA,0xAA,0x00,0xB0,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x54,0x75,0x00,0x58,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xA8,0x0F,0x00,0xA8,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x7C,0x00,0x00,0x5C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0xAE,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0xD7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x80,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0xC0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; +const uint8_t *_I_Scanning_123x52[] = {_I_Scanning_123x52_0}; + +const uint8_t _I_Quest_7x8_0[] = {0x1E,0x33,0x33,0x30,0x18,0x0C,0x00,0x0C,}; +const uint8_t *_I_Quest_7x8[] = {_I_Quest_7x8_0}; + +const uint8_t _I_Unlock_7x8_0[] = {0x1C,0x22,0x02,0x4F,0x67,0x73,0x79,0x3C,}; +const uint8_t *_I_Unlock_7x8[] = {_I_Unlock_7x8_0}; + +const uint8_t _I_Lock_7x8_0[] = {0x1C,0x22,0x22,0x7F,0x7F,0x77,0x7F,0x3E,}; +const uint8_t *_I_Lock_7x8[] = {_I_Lock_7x8_0}; + const uint8_t _I_DolphinMafia_115x62_0[] = {0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x15,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAF,0x0A,0x00,0x40,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x55,0x15,0x00,0x80,0xF0,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xAA,0x0A,0x00,0x80,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x55,0x15,0x00,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xAA,0x2A,0xE0,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x55,0x55,0xFC,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xAA,0xAA,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x55,0xD5,0xFF,0x7F,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xAA,0xFA,0xFF,0x2B,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x55,0xFD,0x7F,0x05,0xE8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAB,0xFE,0xAF,0x00,0xF1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xFF,0x15,0xE0,0x37,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEB,0xFF,0x0A,0xFC,0x7F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF6,0x7F,0x81,0xFF,0xEF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0xFA,0xAF,0xE0,0x3F,0xEE,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0xFE,0x57,0xF8,0x0F,0xCE,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xFF,0x2B,0xFC,0x1F,0x07,0x00,0x30,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0xC0,0xFF,0x15,0xFC,0xFF,0x07,0x00,0xC0,0x00,0x00,0x00,0x00,0x20,0x02,0x00,0xE0,0xBF,0x0A,0xFC,0xFF,0x03,0x00,0x00,0x01,0x00,0x00,0x00,0x18,0x01,0x00,0xF8,0x5F,0x05,0xF8,0xFF,0x03,0x00,0x00,0x02,0x00,0x00,0x60,0x86,0x00,0x00,0xFC,0xAF,0x02,0xFA,0xFF,0x01,0x00,0x00,0x02,0x00,0x30,0x1D,0x40,0x00,0x00,0xFF,0x57,0x01,0xF5,0x7F,0x00,0x00,0xC0,0x02,0x00,0x08,0x00,0x30,0x00,0x80,0xFF,0xAB,0x80,0xEA,0x1F,0x00,0x00,0xE0,0xFB,0x03,0x04,0x00,0x0E,0x00,0xC0,0xFF,0x57,0x00,0xF5,0x03,0x00,0x00,0xF8,0x02,0x00,0x04,0x60,0x01,0x00,0xE0,0xFF,0x2B,0x80,0x0A,0x04,0x00,0x00,0xC6,0xC2,0x0F,0x04,0x03,0x00,0x00,0xF0,0xFF,0x16,0x00,0x05,0x08,0x00,0x80,0x01,0x02,0x00,0xF0,0x00,0x00,0x00,0xF0,0x3F,0x0A,0x80,0x02,0x00,0x00,0x60,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x06,0x00,0x03,0x00,0x00,0x1C,0x00,0x01,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x82,0x00,0x00,0x03,0x80,0x00,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x82,0x00,0xE0,0x00,0x40,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x03,0x1E,0x00,0x30,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0xFC,0x01,0x00,0x0E,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0xC0,0x01,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0xE1,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xF8,0x10,0x03,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0xF0,0x04,0x00,0x00,0x04,0x10,0x04,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x00,0x0F,0x04,0x00,0x00,0x04,0x10,0x08,0x00,0x00,0x00,0xB0,0x01,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x04,0x10,0x08,0x00,0x00,0x00,0xD8,0xFF,0xFF,0xFF,0x3F,0x00,0x28,0x00,0x00,0x08,0x10,0x08,0x00,0x00,0x00,0xEC,0x01,0x00,0x00,0xE0,0x1F,0x28,0x00,0x00,0x10,0x10,0x08,0x00,0x00,0x00,0xD6,0x02,0x00,0x00,0x00,0x30,0x50,0x00,0x00,0x10,0x10,0x04,0x00,0x00,0x00,0xEB,0x05,0x00,0x00,0x00,0x50,0x50,0x00,0x00,0x10,0x20,0x02,0x00,0x00,0x80,0xD4,0x0A,0x00,0x00,0x00,0x90,0x50,0x00,0x00,0x08,0xC0,0x01,0x00,0x00,0x40,0xEA,0x15,0x00,0x00,0x00,0x08,0x61,0x00,0x00,0x0C,0x00,0x01,0x00,0x00,0x20,0xF4,0xFF,0xFF,0x01,0x00,0x08,0x62,0x00,0x00,0x12,0x80,0x00,0x00,0x00,0x10,0xEA,0x15,0x00,0xFE,0x00,0x08,0xE4,0x01,0x00,0x21,0x80,0x00,0x00,0x00,0x10,0xF4,0x0A,0x00,0x00,0x0F,0x04,0xA8,0x06,0xC0,0xC0,0x40,0x00,0x00,0x00,0x08,0xE8,0x05,0x00,0x00,0x30,0x04,0x50,0x19,0x38,0x01,0x47,0x00,0x00,0x00,0x04,0xF4,0x02,0x00,0x00,0xC0,0x04,0xC0,0xE2,0x07,0x06,0x38,0x00,0x00,0x00,0x04,0xF8,0x05,0x00,0x00,0x00,0x03,0x40,0x01,0x00,0x18,0x20,0x00,0x00,0x00,0x02,0xF0,0x02,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x02,0xF8,0x01,0x00,0x00,0x00,0x00,0x80,0x05,0x00,0x80,0x11,0x00,0x00,0x00,0x01,0xF0,0x02,0x00,0x00,0x00,0x00,0x80,0x0A,0x00,0x00,0x0E,0x00,0x00,0x00,}; const uint8_t *_I_DolphinMafia_115x62[] = {_I_DolphinMafia_115x62_0}; @@ -472,10 +478,6 @@ const Icon I_DolphinFirstStart8_56x51 = {.width=56,.height=51,.frame_count=1,.fr const Icon I_DolphinFirstStart7_61x51 = {.width=61,.height=51,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart7_61x51}; const Icon I_Flipper_young_80x60 = {.width=80,.height=60,.frame_count=1,.frame_rate=0,.frames=_I_Flipper_young_80x60}; const Icon I_DolphinFirstStart3_57x48 = {.width=57,.height=48,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart3_57x48}; -const Icon I_Scanning_123x52 = {.width=123,.height=52,.frame_count=1,.frame_rate=0,.frames=_I_Scanning_123x52}; -const Icon I_Quest_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Quest_7x8}; -const Icon I_Unlock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Unlock_7x8}; -const Icon I_Lock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Lock_7x8}; const Icon I_PassportBottom_128x17 = {.width=128,.height=17,.frame_count=1,.frame_rate=0,.frames=_I_PassportBottom_128x17}; const Icon I_DoorLeft_8x56 = {.width=8,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLeft_8x56}; const Icon I_DoorLocked_10x56 = {.width=10,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLocked_10x56}; @@ -510,6 +512,7 @@ const Icon I_KeySaveSelected_24x11 = {.width=24,.height=11,.frame_count=1,.frame const Icon I_KeyBackspace_16x9 = {.width=16,.height=9,.frame_count=1,.frame_rate=0,.frames=_I_KeyBackspace_16x9}; const Icon A_125khz_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_125khz_14}; const Icon A_Bluetooth_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Bluetooth_14}; +const Icon A_Debug_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_Debug_14}; const Icon A_FileManager_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,.frames=_A_FileManager_14}; const Icon A_GPIO_14 = {.width=14,.height=14,.frame_count=8,.frame_rate=3,.frames=_A_GPIO_14}; const Icon A_Games_14 = {.width=14,.height=14,.frame_count=9,.frame_rate=3,.frames=_A_Games_14}; @@ -552,6 +555,10 @@ const Icon I_SDcardFail_11x8 = {.width=11,.height=8,.frame_count=1,.frame_rate=0 const Icon I_USBConnected_15x8 = {.width=15,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_USBConnected_15x8}; const Icon I_Bluetooth_5x8 = {.width=5,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Bluetooth_5x8}; const Icon I_Background_128x11 = {.width=128,.height=11,.frame_count=1,.frame_rate=0,.frames=_I_Background_128x11}; +const Icon I_Scanning_123x52 = {.width=123,.height=52,.frame_count=1,.frame_rate=0,.frames=_I_Scanning_123x52}; +const Icon I_Quest_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Quest_7x8}; +const Icon I_Unlock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Unlock_7x8}; +const Icon I_Lock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Lock_7x8}; const Icon I_DolphinMafia_115x62 = {.width=115,.height=62,.frame_count=1,.frame_rate=0,.frames=_I_DolphinMafia_115x62}; const Icon I_DolphinExcited_64x63 = {.width=64,.height=63,.frame_count=1,.frame_rate=0,.frames=_I_DolphinExcited_64x63}; const Icon I_iButtonDolphinSuccess_109x60 = {.width=109,.height=60,.frame_count=1,.frame_rate=0,.frames=_I_iButtonDolphinSuccess_109x60}; diff --git a/assets/compiled/assets_icons.h b/assets/compiled/assets_icons.h index 689ce0d7..312451f0 100644 --- a/assets/compiled/assets_icons.h +++ b/assets/compiled/assets_icons.h @@ -29,10 +29,6 @@ extern const Icon I_DolphinFirstStart8_56x51; extern const Icon I_DolphinFirstStart7_61x51; extern const Icon I_Flipper_young_80x60; extern const Icon I_DolphinFirstStart3_57x48; -extern const Icon I_Scanning_123x52; -extern const Icon I_Quest_7x8; -extern const Icon I_Unlock_7x8; -extern const Icon I_Lock_7x8; extern const Icon I_PassportBottom_128x17; extern const Icon I_DoorLeft_8x56; extern const Icon I_DoorLocked_10x56; @@ -67,6 +63,7 @@ extern const Icon I_KeySaveSelected_24x11; extern const Icon I_KeyBackspace_16x9; extern const Icon A_125khz_14; extern const Icon A_Bluetooth_14; +extern const Icon A_Debug_14; extern const Icon A_FileManager_14; extern const Icon A_GPIO_14; extern const Icon A_Games_14; @@ -109,6 +106,10 @@ extern const Icon I_SDcardFail_11x8; extern const Icon I_USBConnected_15x8; extern const Icon I_Bluetooth_5x8; extern const Icon I_Background_128x11; +extern const Icon I_Scanning_123x52; +extern const Icon I_Quest_7x8; +extern const Icon I_Unlock_7x8; +extern const Icon I_Lock_7x8; extern const Icon I_DolphinMafia_115x62; extern const Icon I_DolphinExcited_64x63; extern const Icon I_iButtonDolphinSuccess_109x60; diff --git a/assets/icons/MainMenu/Debug_14/frame_01.png b/assets/icons/MainMenu/Debug_14/frame_01.png new file mode 100644 index 0000000000000000000000000000000000000000..59b61fea864f2854e76681ee6649caa68a1819e9 GIT binary patch literal 3704 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 mf7o0O2E%O43}z%LDJ5IBtl3IxXj3Fx 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 literal 0 HcmV?d00001 diff --git a/assets/icons/MainMenu/Debug_14/frame_04.png b/assets/icons/MainMenu/Debug_14/frame_04.png new file mode 100644 index 0000000000000000000000000000000000000000..5f89c2e1b7ba2f6a23d670a80a0ca5250d2172fb GIT binary patch literal 3717 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 literal 0 HcmV?d00001 diff --git a/assets/icons/MainMenu/Debug_14/frame_rate b/assets/icons/MainMenu/Debug_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/Debug_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/GubGHz/Scanning_123x52.png b/assets/icons/SubGhz/Scanning_123x52.png similarity index 100% rename from assets/icons/GubGHz/Scanning_123x52.png rename to assets/icons/SubGhz/Scanning_123x52.png diff --git a/assets/icons/GubGHz/lock_7x8.png b/assets/icons/SubGhz/lock_7x8.png similarity index 100% rename from assets/icons/GubGHz/lock_7x8.png rename to assets/icons/SubGhz/lock_7x8.png diff --git a/assets/icons/GubGHz/quest_7x8.png b/assets/icons/SubGhz/quest_7x8.png similarity index 100% rename from assets/icons/GubGHz/quest_7x8.png rename to assets/icons/SubGhz/quest_7x8.png diff --git a/assets/icons/GubGHz/unlock_7x8.png b/assets/icons/SubGhz/unlock_7x8.png similarity index 100% rename from assets/icons/GubGHz/unlock_7x8.png rename to assets/icons/SubGhz/unlock_7x8.png diff --git a/firmware/targets/f6/furi-hal/furi-hal-bt.c b/firmware/targets/f6/furi-hal/furi-hal-bt.c index ec14e85f..f40f9601 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-bt.c +++ b/firmware/targets/f6/furi-hal/furi-hal-bt.c @@ -43,7 +43,7 @@ bool furi_hal_bt_is_alive() { return APPE_Status() == BleGlueStatusStarted; } -bool furi_hal_bt_wait_transition() { +bool furi_hal_bt_wait_startup() { uint8_t counter = 0; while (APPE_Status() == BleGlueStatusStartup) { osDelay(10); @@ -56,7 +56,7 @@ bool furi_hal_bt_wait_transition() { } bool furi_hal_bt_lock_flash() { - if (!furi_hal_bt_wait_transition()) { + if (!furi_hal_bt_wait_startup()) { return false; } if (APPE_Status() == BleGlueStatusUninitialized) { @@ -100,7 +100,7 @@ void furi_hal_bt_start_packet_rx(uint8_t channel, uint8_t datarate) { } uint16_t furi_hal_bt_stop_packet_test() { - uint16_t num_of_packets; + uint16_t num_of_packets = 0; hci_le_test_end(&num_of_packets); return num_of_packets; } diff --git a/firmware/targets/f6/furi-hal/furi-hal-gpio.c b/firmware/targets/f6/furi-hal/furi-hal-gpio.c index 65a8009b..1de1657f 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-gpio.c +++ b/firmware/targets/f6/furi-hal/furi-hal-gpio.c @@ -151,6 +151,7 @@ void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* c __disable_irq(); uint8_t pin_num = hal_gpio_get_pin_num(gpio); + furi_assert(gpio_interrupt[pin_num].callback == NULL); gpio_interrupt[pin_num].callback = cb; gpio_interrupt[pin_num].context = ctx; gpio_interrupt[pin_num].ready = true; diff --git a/firmware/targets/furi-hal-include/furi-hal-bt.h b/firmware/targets/furi-hal-include/furi-hal-bt.h index d66233a1..801e3c48 100644 --- a/firmware/targets/furi-hal-include/furi-hal-bt.h +++ b/firmware/targets/furi-hal-include/furi-hal-bt.h @@ -19,6 +19,9 @@ void furi_hal_bt_dump_state(string_t buffer); /** Get BT/BLE system component state */ bool furi_hal_bt_is_alive(); +/** Wait for Core2 startup */ +bool furi_hal_bt_wait_startup(); + /** * Lock shared access to flash controller * @return true if lock was successful, false if not From ae08c88bd6642bba88385c0396b58c977fdbb46a Mon Sep 17 00:00:00 2001 From: its your bedtime <23366927+itsyourbedtime@users.noreply.github.com> Date: Thu, 2 Sep 2021 12:02:34 +0300 Subject: [PATCH 2/5] [FL-1472] Infrared: long names fix (#679) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Infrared app: fix long button names * Ble: fix missing icon on start without config. * Gui: slow but nice string fitting. * Gui: fit header string in button menu Co-authored-by: あく --- applications/bt/bt_service/bt.c | 10 +++++----- applications/gui/elements.c | 10 +++++----- applications/gui/modules/button_menu.c | 15 +++++++++++++-- applications/gui/modules/submenu.c | 9 ++++++++- applications/irda/irda-app-remote-manager.h | 4 ++-- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/applications/bt/bt_service/bt.c b/applications/bt/bt_service/bt.c index 76d4ae10..785573f2 100644 --- a/applications/bt/bt_service/bt.c +++ b/applications/bt/bt_service/bt.c @@ -48,11 +48,11 @@ int32_t bt_srv() { furi_record_create("bt", bt); furi_hal_bt_init(); - if(bt->bt_settings.enabled) { - if(!furi_hal_bt_wait_startup()) { - FURI_LOG_E(BT_SERVICE_TAG, "Core2 startup failed"); - } else { - view_port_enabled_set(bt->statusbar_view_port, true); + if(!furi_hal_bt_wait_startup()) { + FURI_LOG_E(BT_SERVICE_TAG, "Core2 startup failed"); + } else { + view_port_enabled_set(bt->statusbar_view_port, true); + if(bt->bt_settings.enabled) { bool bt_app_started = furi_hal_bt_start_app(); if(!bt_app_started) { FURI_LOG_E(BT_SERVICE_TAG, "BT App start failed"); diff --git a/applications/gui/elements.c b/applications/gui/elements.c index d4dc9aa7..332baa71 100644 --- a/applications/gui/elements.c +++ b/applications/gui/elements.c @@ -332,12 +332,12 @@ void elements_string_fit_width(Canvas* canvas, string_t string, uint8_t width) { furi_assert(string); uint16_t len_px = canvas_string_width(canvas, string_get_cstr(string)); - if(len_px > width) { - size_t s_len = string_size(string); - uint8_t end_pos = s_len - ((len_px - width) / ((len_px / s_len) + 2) + 2); - - string_mid(string, 0, end_pos); + width -= canvas_string_width(canvas, "..."); + do { + string_left(string, string_size(string) - 1); + len_px = canvas_string_width(canvas, string_get_cstr(string)); + } while(len_px > width); string_cat(string, "..."); } } diff --git a/applications/gui/modules/button_menu.c b/applications/gui/modules/button_menu.c index e342162e..81958f0d 100644 --- a/applications/gui/modules/button_menu.c +++ b/applications/gui/modules/button_menu.c @@ -78,13 +78,20 @@ static void button_menu_draw_common_button( } else { canvas_draw_rframe(canvas, item_x, item_y, ITEM_WIDTH, ITEM_HEIGHT, 5); } + + string_t disp_str; + string_init_set_str(disp_str, text); + elements_string_fit_width(canvas, disp_str, ITEM_WIDTH - 6); + canvas_draw_str_aligned( canvas, item_x + (ITEM_WIDTH / 2), item_y + (ITEM_HEIGHT / 2), AlignCenter, AlignCenter, - text); + string_get_cstr(disp_str)); + + string_clear(disp_str); } static void button_menu_view_draw_callback(Canvas* canvas, void* _model) { @@ -110,7 +117,11 @@ static void button_menu_view_draw_callback(Canvas* canvas, void* _model) { canvas_draw_icon(canvas, 28, 123, &I_IrdaArrowDown_4x8); } - canvas_draw_str_aligned(canvas, 32, 10, AlignCenter, AlignCenter, model->header); + string_t disp_str; + string_init_set_str(disp_str, model->header); + elements_string_fit_width(canvas, disp_str, ITEM_WIDTH - 6); + canvas_draw_str_aligned(canvas, 32, 10, AlignCenter, AlignCenter, string_get_cstr(disp_str)); + string_clear(disp_str); for(ButtonMenuItemArray_it(it, model->items); !ButtonMenuItemArray_end_p(it); ButtonMenuItemArray_next(it), ++item_position) { diff --git a/applications/gui/modules/submenu.c b/applications/gui/modules/submenu.c index c1920662..7c12eebc 100644 --- a/applications/gui/modules/submenu.c +++ b/applications/gui/modules/submenu.c @@ -65,11 +65,18 @@ static void submenu_view_draw_callback(Canvas* canvas, void* _model) { } else { canvas_set_color(canvas, ColorBlack); } + + string_t disp_str; + string_init_set_str(disp_str, SubmenuItemArray_cref(it)->label); + elements_string_fit_width(canvas, disp_str, item_width - 20); + canvas_draw_str( canvas, 6, y_offset + (item_position * item_height) + item_height - 4, - SubmenuItemArray_cref(it)->label); + string_get_cstr(disp_str)); + + string_clear(disp_str); } position++; diff --git a/applications/irda/irda-app-remote-manager.h b/applications/irda/irda-app-remote-manager.h index b2a0197f..2b157329 100644 --- a/applications/irda/irda-app-remote-manager.h +++ b/applications/irda/irda-app-remote-manager.h @@ -47,8 +47,8 @@ class IrdaAppRemoteManager { std::string make_remote_name(const std::string& full_name) const; public: - static inline const uint32_t max_button_name_length = 31; - static inline const uint32_t max_remote_name_length = 31; + static inline const uint32_t max_button_name_length = 22; + static inline const uint32_t max_remote_name_length = 22; bool add_remote_with_button(const char* button_name, const IrdaAppSignal& signal); bool add_button(const char* button_name, const IrdaAppSignal& signal); From 4b7d9b79a98253d199d92cf6375e86eedfec365e Mon Sep 17 00:00:00 2001 From: gornekich Date: Thu, 2 Sep 2021 12:28:40 +0300 Subject: [PATCH 3/5] [FL-1748] NFC, iButton edit fix (#680) * nfc: fix edit UID without confirmation * ibutton: fix key edit * nfc: fix nfc uid edition * nfc: fix structure type name --- .../ibutton/scene/ibutton-scene-add-value.cpp | 11 +++-------- applications/ibutton/scene/ibutton-scene-add-value.h | 2 ++ applications/nfc/nfc_i.h | 1 + applications/nfc/scenes/nfc_scene_save_name.c | 3 +++ applications/nfc/scenes/nfc_scene_set_uid.c | 5 +++-- 5 files changed, 12 insertions(+), 10 deletions(-) mode change 100644 => 100755 applications/ibutton/scene/ibutton-scene-add-value.cpp diff --git a/applications/ibutton/scene/ibutton-scene-add-value.cpp b/applications/ibutton/scene/ibutton-scene-add-value.cpp old mode 100644 new mode 100755 index 5f8e9f66..523af8d2 --- a/applications/ibutton/scene/ibutton-scene-add-value.cpp +++ b/applications/ibutton/scene/ibutton-scene-add-value.cpp @@ -8,14 +8,9 @@ void iButtonSceneAddValue::on_enter(iButtonApp* app) { iButtonAppViewManager* view_manager = app->get_view_manager(); ByteInput* byte_input = view_manager->get_byte_input(); auto callback = cbc::obtain_connector(this, &iButtonSceneAddValue::byte_input_callback); - + memcpy(this->new_key_data, app->get_key()->get_data(), app->get_key()->get_type_data_size()); byte_input_set_result_callback( - byte_input, - callback, - NULL, - app, - app->get_key()->get_data(), - app->get_key()->get_type_data_size()); + byte_input, callback, NULL, app, this->new_key_data, app->get_key()->get_type_data_size()); byte_input_set_header_text(byte_input, "Enter the key"); view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewByteInput); @@ -45,6 +40,6 @@ void iButtonSceneAddValue::byte_input_callback(void* context) { iButtonEvent event; event.type = iButtonEvent::Type::EventTypeByteEditResult; - + memcpy(app->get_key()->get_data(), this->new_key_data, app->get_key()->get_type_data_size()); app->get_view_manager()->send_event(&event); } \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton-scene-add-value.h b/applications/ibutton/scene/ibutton-scene-add-value.h index ed9df460..8429e47a 100644 --- a/applications/ibutton/scene/ibutton-scene-add-value.h +++ b/applications/ibutton/scene/ibutton-scene-add-value.h @@ -1,5 +1,6 @@ #pragma once #include "ibutton-scene-generic.h" +#include "../ibutton-key.h" class iButtonSceneAddValue : public iButtonScene { public: @@ -9,4 +10,5 @@ public: private: void byte_input_callback(void* context); + uint8_t new_key_data[IBUTTON_KEY_DATA_SIZE] = {}; }; \ No newline at end of file diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 54b68231..53fd6689 100755 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -35,6 +35,7 @@ struct Nfc { NotificationApp* notifications; SceneManager* scene_manager; NfcDevice dev; + NfcDeviceCommonData dev_edit_data; char text_store[NFC_TEXT_STORE_SIZE + 1]; string_t text_box_store; diff --git a/applications/nfc/scenes/nfc_scene_save_name.c b/applications/nfc/scenes/nfc_scene_save_name.c index 4a0041b2..ca239f68 100755 --- a/applications/nfc/scenes/nfc_scene_save_name.c +++ b/applications/nfc/scenes/nfc_scene_save_name.c @@ -40,6 +40,9 @@ const bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) if(nfc->dev.dev_name) { nfc_device_delete(&nfc->dev); } + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) { + nfc->dev.dev_data.nfc_data = nfc->dev_edit_data; + } memcpy(&nfc->dev.dev_name, nfc->text_store, strlen(nfc->text_store)); if(nfc_device_save(&nfc->dev, nfc->text_store)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); diff --git a/applications/nfc/scenes/nfc_scene_set_uid.c b/applications/nfc/scenes/nfc_scene_set_uid.c index 6e1a8d7c..dd448a78 100755 --- a/applications/nfc/scenes/nfc_scene_set_uid.c +++ b/applications/nfc/scenes/nfc_scene_set_uid.c @@ -14,13 +14,14 @@ const void nfc_scene_set_uid_on_enter(void* context) { // Setup view ByteInput* byte_input = nfc->byte_input; byte_input_set_header_text(byte_input, "Enter uid in hex"); + nfc->dev_edit_data = nfc->dev.dev_data.nfc_data; byte_input_set_result_callback( byte_input, nfc_scene_set_uid_byte_input_callback, NULL, nfc, - nfc->dev.dev_data.nfc_data.uid, - nfc->dev.dev_data.nfc_data.uid_len); + nfc->dev_edit_data.uid, + nfc->dev_edit_data.uid_len); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput); } From 94f161d1605062d1fb226218db587bf1610bc41b Mon Sep 17 00:00:00 2001 From: Anna Prosvetova Date: Fri, 3 Sep 2021 01:44:37 +0300 Subject: [PATCH 4/5] Toolchain: Fix GDB (#686) --- docker/Dockerfile | 6 +++++- docker/entrypoint.sh | 8 -------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 547c2bc3..806535ce 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,7 +4,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-instal ca-certificates \ build-essential \ python3 \ - python3-lxml \ + python-setuptools \ + libpython2.7 \ git \ clang-format-12 \ dfu-util \ @@ -22,6 +23,9 @@ RUN wget --progress=dot:giga "https://developer.arm.com/-/media/Files/downloads/ for file in * ; do ln -s "${PWD}/${file}" "/usr/bin/${file}" ; done && \ cd / && arm-none-eabi-gcc -v && arm-none-eabi-gdb -v +RUN wget --progress=dot:giga -O - https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2 && \ + pip install --no-cache-dir lxml==4.6.3 + RUN git clone https://github.com/rusdacent/hex2dfu.git && \ cd hex2dfu && gcc hex2dfu.c ED25519/*.c -o hex2dfu && mv ./hex2dfu /usr/local/bin/hex2dfu && \ hex2dfu -h diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 3693363e..4d553e0b 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,13 +1,5 @@ #!/bin/bash -# A hack for GitHub Actions to not install Rust twice -if [ "$HOME" != "/root" ]; then - ln -sf /root/.rustup "$HOME/.rustup" - ln -sf /root/.cargo "$HOME/.cargo" -fi - -PATH="$HOME/.cargo/bin:${PATH}" - if [ -z "$1" ]; then bash else From 5443bede534044b8eb3c83fd4a34c46252880860 Mon Sep 17 00:00:00 2001 From: Anna Prosvetova Date: Fri, 3 Sep 2021 16:57:43 +0300 Subject: [PATCH 5/5] Toolchain: Add missing dependencies (#687) --- docker/Dockerfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 806535ce..93655a9c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,14 +4,17 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-instal ca-certificates \ build-essential \ python3 \ - python-setuptools \ - libpython2.7 \ git \ clang-format-12 \ dfu-util \ openocd \ srecord \ libncurses5 \ + python-setuptools \ + libpython2.7-dev \ + libxml2-dev \ + libxslt1-dev \ + zlib1g-dev \ wget && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*