[FL-1720] BLE GUI refactoring (#678)
* 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: あく <alleteam@gmail.com>
@ -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 *****************************/
|
||||
|
@ -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() {
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
}
|
94
applications/bt/bt_debug_app/bt_debug_app.c
Executable file
@ -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;
|
||||
}
|
26
applications/bt/bt_debug_app/bt_debug_app.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
|
||||
#include <gui/modules/submenu.h>
|
||||
#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;
|
188
applications/bt/bt_debug_app/views/bt_carrier_test.c
Executable file
@ -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);
|
||||
}
|
10
applications/bt/bt_debug_app/views/bt_carrier_test.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <gui/view.h>
|
||||
|
||||
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);
|
155
applications/bt/bt_debug_app/views/bt_packet_test.c
Normal file
@ -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);
|
||||
}
|
10
applications/bt/bt_debug_app/views/bt_packet_test.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <gui/view.h>
|
||||
|
||||
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);
|
422
applications/bt/bt_debug_app/views/bt_test.c
Executable file
@ -0,0 +1,422 @@
|
||||
#include "bt_test.h"
|
||||
|
||||
#include <gui/canvas.h>
|
||||
#include <gui/elements.h>
|
||||
#include <m-array.h>
|
||||
#include <m-string.h>
|
||||
#include <furi.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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;
|
||||
}
|
46
applications/bt/bt_debug_app/views/bt_test.h
Executable file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include <gui/view.h>
|
||||
|
||||
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);
|
30
applications/bt/bt_debug_app/views/bt_test_types.h
Normal file
@ -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;
|
@ -1,53 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "bt.h"
|
||||
#include "bt_views.h"
|
||||
#include "bt_types.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
|
||||
#include <cli/cli.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_port.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
|
||||
#include <menu/menu.h>
|
||||
#include <menu/menu_item.h>
|
||||
|
||||
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);
|
74
applications/bt/bt_service/bt.c
Normal file
@ -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;
|
||||
}
|
29
applications/bt/bt_service/bt_i.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "bt.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_port.h>
|
||||
#include <gui/view.h>
|
||||
|
||||
#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;
|
||||
};
|
50
applications/bt/bt_settings.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include "bt_settings.h"
|
||||
#include <furi.h>
|
||||
#include <file-worker.h>
|
||||
|
||||
#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;
|
||||
}
|
15
applications/bt/bt_settings.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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);
|
67
applications/bt/bt_settings_app/bt_settings_app.c
Executable file
@ -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;
|
||||
}
|
27
applications/bt/bt_settings_app/bt_settings_app.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/dialog_ex.h>
|
||||
|
||||
#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;
|
30
applications/bt/bt_settings_app/scenes/bt_settings_scene.c
Normal file
@ -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,
|
||||
};
|
29
applications/bt/bt_settings_app/scenes/bt_settings_scene.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// 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
|
@ -0,0 +1,2 @@
|
||||
ADD_SCENE(bt_settings, start, Start)
|
||||
ADD_SCENE(bt_settings, disable_dialog, DisableDialog)
|
44
applications/bt/bt_settings_app/scenes/bt_settings_scene_disable_dialog.c
Executable file
@ -0,0 +1,44 @@
|
||||
#include "../bt_settings_app.h"
|
||||
#include <furi-hal-boot.h>
|
||||
#include <furi-hal-power.h>
|
||||
|
||||
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);
|
||||
}
|
56
applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c
Executable file
@ -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);
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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;
|
@ -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;
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "bt_i.h"
|
||||
#include "bt_types.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <gui/canvas.h>
|
||||
#include <furi.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/view.h>
|
||||
|
||||
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);
|
19
applications/gui/modules/dialog_ex.c
Normal file → Executable file
@ -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;
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
BIN
assets/icons/MainMenu/Debug_14/frame_01.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
assets/icons/MainMenu/Debug_14/frame_02.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
assets/icons/MainMenu/Debug_14/frame_03.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
assets/icons/MainMenu/Debug_14/frame_04.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
1
assets/icons/MainMenu/Debug_14/frame_rate
Normal file
@ -0,0 +1 @@
|
||||
3
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|