mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 16:28:36 -07:00
Merge branch 'flipperdevices:dev' into dev
This commit is contained in:
@@ -32,7 +32,6 @@ void AccessorApp::run(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AccessorApp::AccessorApp() {
|
AccessorApp::AccessorApp() {
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
|
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
|
||||||
onewire_host = onewire_host_alloc();
|
onewire_host = onewire_host_alloc();
|
||||||
furi_hal_power_enable_otg();
|
furi_hal_power_enable_otg();
|
||||||
@@ -42,7 +41,6 @@ AccessorApp::~AccessorApp() {
|
|||||||
furi_hal_power_disable_otg();
|
furi_hal_power_disable_otg();
|
||||||
furi_record_close("notification");
|
furi_record_close("notification");
|
||||||
onewire_host_free(onewire_host);
|
onewire_host_free(onewire_host);
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessorAppViewManager* AccessorApp::get_view_manager() {
|
AccessorAppViewManager* AccessorApp::get_view_manager() {
|
||||||
@@ -139,4 +137,4 @@ WIEGAND* AccessorApp::get_wiegand() {
|
|||||||
|
|
||||||
OneWireHost* AccessorApp::get_one_wire() {
|
OneWireHost* AccessorApp::get_one_wire() {
|
||||||
return onewire_host;
|
return onewire_host;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,61 +74,113 @@ extern int32_t system_settings_app(void* p);
|
|||||||
const FlipperApplication FLIPPER_SERVICES[] = {
|
const FlipperApplication FLIPPER_SERVICES[] = {
|
||||||
/* Services */
|
/* Services */
|
||||||
#ifdef SRV_RPC
|
#ifdef SRV_RPC
|
||||||
{.app = rpc_srv, .name = "RpcSrv", .stack_size = 1024 * 4, .icon = NULL},
|
{.app = rpc_srv,
|
||||||
|
.name = "RpcSrv",
|
||||||
|
.stack_size = 1024 * 4,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_BT
|
#ifdef SRV_BT
|
||||||
{.app = bt_srv, .name = "BtSrv", .stack_size = 1024, .icon = NULL},
|
{.app = bt_srv,
|
||||||
|
.name = "BtSrv",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_CLI
|
#ifdef SRV_CLI
|
||||||
{.app = cli_srv, .name = "CliSrv", .stack_size = 4096, .icon = NULL},
|
{.app = cli_srv,
|
||||||
|
.name = "CliSrv",
|
||||||
|
.stack_size = 4096,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_DIALOGS
|
#ifdef SRV_DIALOGS
|
||||||
{.app = dialogs_srv, .name = "DialogsSrv", .stack_size = 1024, .icon = NULL},
|
{.app = dialogs_srv,
|
||||||
|
.name = "DialogsSrv",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_DOLPHIN
|
#ifdef SRV_DOLPHIN
|
||||||
{.app = dolphin_srv, .name = "DolphinSrv", .stack_size = 1024, .icon = NULL},
|
{.app = dolphin_srv,
|
||||||
|
.name = "DolphinSrv",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_DESKTOP
|
#ifdef SRV_DESKTOP
|
||||||
#ifdef SRV_UPDATER
|
#ifdef SRV_UPDATER
|
||||||
#error SRV_UPDATER and SRV_DESKTOP are mutually exclusive!
|
#error SRV_UPDATER and SRV_DESKTOP are mutually exclusive!
|
||||||
#endif
|
#endif
|
||||||
{.app = desktop_srv, .name = "DesktopSrv", .stack_size = 2048, .icon = NULL},
|
{.app = desktop_srv,
|
||||||
|
.name = "DesktopSrv",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_GUI
|
#ifdef SRV_GUI
|
||||||
{.app = gui_srv, .name = "GuiSrv", .stack_size = 2048, .icon = NULL},
|
{.app = gui_srv,
|
||||||
|
.name = "GuiSrv",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_INPUT
|
#ifdef SRV_INPUT
|
||||||
{.app = input_srv, .name = "InputSrv", .stack_size = 1024, .icon = NULL},
|
{.app = input_srv,
|
||||||
|
.name = "InputSrv",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_LOADER
|
#ifdef SRV_LOADER
|
||||||
{.app = loader_srv, .name = "LoaderSrv", .stack_size = 1024, .icon = NULL},
|
{.app = loader_srv,
|
||||||
|
.name = "LoaderSrv",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_NOTIFICATION
|
#ifdef SRV_NOTIFICATION
|
||||||
{.app = notification_srv, .name = "NotificationSrv", .stack_size = 1536, .icon = NULL},
|
{.app = notification_srv,
|
||||||
|
.name = "NotificationSrv",
|
||||||
|
.stack_size = 1536,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_POWER
|
#ifdef SRV_POWER
|
||||||
{.app = power_srv, .name = "PowerSrv", .stack_size = 1024, .icon = NULL},
|
{.app = power_srv,
|
||||||
|
.name = "PowerSrv",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_STORAGE
|
#ifdef SRV_STORAGE
|
||||||
{.app = storage_srv, .name = "StorageSrv", .stack_size = 3072, .icon = NULL},
|
{.app = storage_srv,
|
||||||
|
.name = "StorageSrv",
|
||||||
|
.stack_size = 3072,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_UPDATER
|
#ifdef SRV_UPDATER
|
||||||
#ifdef SRV_DESKTOP
|
#ifdef SRV_DESKTOP
|
||||||
#error SRV_UPDATER and SRV_DESKTOP are mutually exclusive!
|
#error SRV_UPDATER and SRV_DESKTOP are mutually exclusive!
|
||||||
#endif
|
#endif
|
||||||
{.app = updater_srv, .name = "UpdaterSrv", .stack_size = 2048, .icon = NULL},
|
{.app = updater_srv,
|
||||||
|
.name = "UpdaterSrv",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -139,7 +191,11 @@ const FlipperApplication FLIPPER_SYSTEM_APPS[] = {
|
|||||||
#ifdef SRV_UPDATER
|
#ifdef SRV_UPDATER
|
||||||
#error APP_UPDATER and SRV_UPDATER are mutually exclusive!
|
#error APP_UPDATER and SRV_UPDATER are mutually exclusive!
|
||||||
#endif
|
#endif
|
||||||
{.app = updater_srv, .name = "UpdaterApp", .stack_size = 2048, .icon = NULL},
|
{.app = updater_srv,
|
||||||
|
.name = "UpdaterApp",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -149,35 +205,67 @@ const size_t FLIPPER_SYSTEM_APPS_COUNT = COUNT_OF(FLIPPER_SYSTEM_APPS);
|
|||||||
const FlipperApplication FLIPPER_APPS[] = {
|
const FlipperApplication FLIPPER_APPS[] = {
|
||||||
|
|
||||||
#ifdef APP_SUBGHZ
|
#ifdef APP_SUBGHZ
|
||||||
{.app = subghz_app, .name = "Sub-GHz", .stack_size = 2048, .icon = &A_Sub1ghz_14},
|
{.app = subghz_app,
|
||||||
|
.name = "Sub-GHz",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = &A_Sub1ghz_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_LF_RFID
|
#ifdef APP_LF_RFID
|
||||||
{.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 2048, .icon = &A_125khz_14},
|
{.app = lfrfid_app,
|
||||||
|
.name = "125 kHz RFID",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = &A_125khz_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_NFC
|
#ifdef APP_NFC
|
||||||
{.app = nfc_app, .name = "NFC", .stack_size = 4096, .icon = &A_NFC_14},
|
{.app = nfc_app,
|
||||||
|
.name = "NFC",
|
||||||
|
.stack_size = 4096,
|
||||||
|
.icon = &A_NFC_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_INFRARED
|
#ifdef APP_INFRARED
|
||||||
{.app = infrared_app, .name = "Infrared", .stack_size = 1024 * 3, .icon = &A_Infrared_14},
|
{.app = infrared_app,
|
||||||
|
.name = "Infrared",
|
||||||
|
.stack_size = 1024 * 3,
|
||||||
|
.icon = &A_Infrared_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_GPIO
|
#ifdef APP_GPIO
|
||||||
{.app = gpio_app, .name = "GPIO", .stack_size = 1024, .icon = &A_GPIO_14},
|
{.app = gpio_app,
|
||||||
|
.name = "GPIO",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = &A_GPIO_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_IBUTTON
|
#ifdef APP_IBUTTON
|
||||||
{.app = ibutton_app, .name = "iButton", .stack_size = 2048, .icon = &A_iButton_14},
|
{.app = ibutton_app,
|
||||||
|
.name = "iButton",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = &A_iButton_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_BAD_USB
|
#ifdef APP_BAD_USB
|
||||||
{.app = bad_usb_app, .name = "Bad USB", .stack_size = 2048, .icon = &A_BadUsb_14},
|
{.app = bad_usb_app,
|
||||||
|
.name = "Bad USB",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = &A_BadUsb_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_U2F
|
#ifdef APP_U2F
|
||||||
{.app = u2f_app, .name = "U2F", .stack_size = 2048, .icon = &A_U2F_14},
|
{.app = u2f_app,
|
||||||
|
.name = "U2F",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = &A_U2F_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -234,15 +322,27 @@ const size_t FLIPPER_ON_SYSTEM_START_COUNT = COUNT_OF(FLIPPER_ON_SYSTEM_START);
|
|||||||
// Plugin menu
|
// Plugin menu
|
||||||
const FlipperApplication FLIPPER_PLUGINS[] = {
|
const FlipperApplication FLIPPER_PLUGINS[] = {
|
||||||
#ifdef APP_BLE_HID
|
#ifdef APP_BLE_HID
|
||||||
{.app = bt_hid_app, .name = "Bluetooth Remote", .stack_size = 1024, .icon = NULL},
|
{.app = bt_hid_app,
|
||||||
|
.name = "Bluetooth Remote",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_MUSIC_PLAYER
|
#ifdef APP_MUSIC_PLAYER
|
||||||
{.app = music_player_app, .name = "Music Player", .stack_size = 1024, .icon = &A_Plugins_14},
|
{.app = music_player_app,
|
||||||
|
.name = "Music Player",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = &A_Plugins_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_SNAKE_GAME
|
#ifdef APP_SNAKE_GAME
|
||||||
{.app = snake_game_app, .name = "Snake Game", .stack_size = 1024, .icon = &A_Plugins_14},
|
{.app = snake_game_app,
|
||||||
|
.name = "Snake Game",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = &A_Plugins_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -251,108 +351,201 @@ const size_t FLIPPER_PLUGINS_COUNT = COUNT_OF(FLIPPER_PLUGINS);
|
|||||||
// Plugin menu
|
// Plugin menu
|
||||||
const FlipperApplication FLIPPER_DEBUG_APPS[] = {
|
const FlipperApplication FLIPPER_DEBUG_APPS[] = {
|
||||||
#ifdef APP_BLINK
|
#ifdef APP_BLINK
|
||||||
{.app = blink_test_app, .name = "Blink Test", .stack_size = 1024, .icon = NULL},
|
{.app = blink_test_app,
|
||||||
|
.name = "Blink Test",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_VIBRO_TEST
|
#ifdef APP_VIBRO_TEST
|
||||||
{.app = vibro_test_app, .name = "Vibro Test", .stack_size = 1024, .icon = NULL},
|
{.app = vibro_test_app,
|
||||||
|
.name = "Vibro Test",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_KEYPAD_TEST
|
#ifdef APP_KEYPAD_TEST
|
||||||
{.app = keypad_test_app, .name = "Keypad Test", .stack_size = 1024, .icon = NULL},
|
{.app = keypad_test_app,
|
||||||
|
.name = "Keypad Test",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_ACCESSOR
|
#ifdef APP_ACCESSOR
|
||||||
{.app = accessor_app, .name = "Accessor", .stack_size = 4096, .icon = NULL},
|
{.app = accessor_app,
|
||||||
|
.name = "Accessor",
|
||||||
|
.stack_size = 4096,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_USB_TEST
|
#ifdef APP_USB_TEST
|
||||||
{.app = usb_test_app, .name = "USB Test", .stack_size = 1024, .icon = NULL},
|
{.app = usb_test_app,
|
||||||
|
.name = "USB Test",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_USB_MOUSE
|
#ifdef APP_USB_MOUSE
|
||||||
{.app = usb_mouse_app, .name = "USB Mouse Demo", .stack_size = 1024, .icon = NULL},
|
{.app = usb_mouse_app,
|
||||||
|
.name = "USB Mouse Demo",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_UART_ECHO
|
#ifdef APP_UART_ECHO
|
||||||
{.app = uart_echo_app, .name = "Uart Echo", .stack_size = 2048, .icon = NULL},
|
{.app = uart_echo_app,
|
||||||
|
.name = "Uart Echo",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_INFRARED_MONITOR
|
#ifdef APP_INFRARED_MONITOR
|
||||||
{.app = infrared_monitor_app, .name = "Infrared Monitor", .stack_size = 1024, .icon = NULL},
|
{.app = infrared_monitor_app,
|
||||||
|
.name = "Infrared Monitor",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_SCENED
|
#ifdef APP_SCENED
|
||||||
{.app = scened_app, .name = "Templated Scene", .stack_size = 1024, .icon = NULL},
|
{.app = scened_app,
|
||||||
|
.name = "Templated Scene",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_LF_RFID
|
#ifdef APP_LF_RFID
|
||||||
{.app = lfrfid_debug_app, .name = "LF-RFID Debug", .stack_size = 1024, .icon = NULL},
|
{.app = lfrfid_debug_app,
|
||||||
|
.name = "LF-RFID Debug",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_BT
|
#ifdef SRV_BT
|
||||||
{.app = bt_debug_app, .name = "Bluetooth Debug", .stack_size = 1024, .icon = NULL},
|
{.app = bt_debug_app,
|
||||||
|
.name = "Bluetooth Debug",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_UNIT_TESTS
|
#ifdef APP_UNIT_TESTS
|
||||||
{.app = delay_test_app, .name = "Delay Test", .stack_size = 1024, .icon = NULL},
|
{.app = delay_test_app,
|
||||||
|
.name = "Delay Test",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_DISPLAY_TEST
|
#ifdef APP_DISPLAY_TEST
|
||||||
{.app = display_test_app, .name = "Display Test", .stack_size = 1024, .icon = NULL},
|
{.app = display_test_app,
|
||||||
|
.name = "Display Test",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_BATTERY_TEST
|
#ifdef APP_BATTERY_TEST
|
||||||
{.app = battery_test_app, .name = "Battery Test", .stack_size = 1024, .icon = NULL},
|
{.app = battery_test_app,
|
||||||
|
.name = "Battery Test",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_TEXT_BOX_TEST
|
#ifdef APP_TEXT_BOX_TEST
|
||||||
{.app = text_box_test_app, .name = "Text Box Test", .stack_size = 1024, .icon = NULL},
|
{.app = text_box_test_app,
|
||||||
|
.name = "Text Box Test",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t FLIPPER_DEBUG_APPS_COUNT = COUNT_OF(FLIPPER_DEBUG_APPS);
|
const size_t FLIPPER_DEBUG_APPS_COUNT = COUNT_OF(FLIPPER_DEBUG_APPS);
|
||||||
|
|
||||||
#ifdef APP_ARCHIVE
|
#ifdef APP_ARCHIVE
|
||||||
const FlipperApplication FLIPPER_ARCHIVE =
|
const FlipperApplication FLIPPER_ARCHIVE = {
|
||||||
{.app = archive_app, .name = "Archive", .stack_size = 4096, .icon = &A_FileManager_14};
|
.app = archive_app,
|
||||||
|
.name = "Archive",
|
||||||
|
.stack_size = 4096,
|
||||||
|
.icon = &A_FileManager_14,
|
||||||
|
.flags = FlipperApplicationFlagDefault};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Settings menu
|
// Settings menu
|
||||||
const FlipperApplication FLIPPER_SETTINGS_APPS[] = {
|
const FlipperApplication FLIPPER_SETTINGS_APPS[] = {
|
||||||
#ifdef SRV_BT
|
#ifdef SRV_BT
|
||||||
{.app = bt_settings_app, .name = "Bluetooth", .stack_size = 1024, .icon = NULL},
|
{.app = bt_settings_app,
|
||||||
|
.name = "Bluetooth",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_NOTIFICATION
|
#ifdef SRV_NOTIFICATION
|
||||||
{.app = notification_settings_app,
|
{.app = notification_settings_app,
|
||||||
.name = "LCD and Notifications",
|
.name = "LCD and Notifications",
|
||||||
.stack_size = 1024,
|
.stack_size = 1024,
|
||||||
.icon = NULL},
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_STORAGE
|
#ifdef SRV_STORAGE
|
||||||
{.app = storage_settings_app, .name = "Storage", .stack_size = 2048, .icon = NULL},
|
{.app = storage_settings_app,
|
||||||
|
.name = "Storage",
|
||||||
|
.stack_size = 2048,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_POWER
|
#ifdef SRV_POWER
|
||||||
{.app = power_settings_app, .name = "Power", .stack_size = 1024, .icon = NULL},
|
{.app = power_settings_app,
|
||||||
|
.name = "Power",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagInsomniaSafe},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_DESKTOP
|
#ifdef SRV_DESKTOP
|
||||||
{.app = desktop_settings_app, .name = "Desktop", .stack_size = 1024, .icon = NULL},
|
{.app = desktop_settings_app,
|
||||||
|
.name = "Desktop",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_PASSPORT
|
#ifdef APP_PASSPORT
|
||||||
{.app = passport_app, .name = "Passport", .stack_size = 1024, .icon = NULL},
|
{.app = passport_app,
|
||||||
|
.name = "Passport",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SRV_GUI
|
#ifdef SRV_GUI
|
||||||
{.app = system_settings_app, .name = "System", .stack_size = 1024, .icon = NULL},
|
{.app = system_settings_app,
|
||||||
|
.name = "System",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef APP_ABOUT
|
#ifdef APP_ABOUT
|
||||||
{.app = about_settings_app, .name = "About", .stack_size = 1024, .icon = NULL},
|
{.app = about_settings_app,
|
||||||
|
.name = "About",
|
||||||
|
.stack_size = 1024,
|
||||||
|
.icon = NULL,
|
||||||
|
.flags = FlipperApplicationFlagDefault},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,17 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <gui/icon.h>
|
#include <gui/icon.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FlipperApplicationFlagDefault = 0,
|
||||||
|
FlipperApplicationFlagInsomniaSafe = (1 << 0),
|
||||||
|
} FlipperApplicationFlag;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const FuriThreadCallback app;
|
const FuriThreadCallback app;
|
||||||
const char* name;
|
const char* name;
|
||||||
const size_t stack_size;
|
const size_t stack_size;
|
||||||
const Icon* icon;
|
const Icon* icon;
|
||||||
|
const FlipperApplicationFlag flags;
|
||||||
} FlipperApplication;
|
} FlipperApplication;
|
||||||
|
|
||||||
typedef void (*FlipperOnStartHook)(void);
|
typedef void (*FlipperOnStartHook)(void);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ static ViewPort* bt_pin_code_view_port_alloc(Bt* bt) {
|
|||||||
|
|
||||||
static void bt_pin_code_show(Bt* bt, uint32_t pin_code) {
|
static void bt_pin_code_show(Bt* bt, uint32_t pin_code) {
|
||||||
bt->pin_code = pin_code;
|
bt->pin_code = pin_code;
|
||||||
notification_message(bt->notification, &sequence_display_on);
|
notification_message(bt->notification, &sequence_display_backlight_on);
|
||||||
gui_view_port_send_to_front(bt->gui, bt->pin_code_view_port);
|
gui_view_port_send_to_front(bt->gui, bt->pin_code_view_port);
|
||||||
view_port_enabled_set(bt->pin_code_view_port, true);
|
view_port_enabled_set(bt->pin_code_view_port, true);
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ static void bt_pin_code_hide(Bt* bt) {
|
|||||||
|
|
||||||
static bool bt_pin_code_verify_event_handler(Bt* bt, uint32_t pin) {
|
static bool bt_pin_code_verify_event_handler(Bt* bt, uint32_t pin) {
|
||||||
furi_assert(bt);
|
furi_assert(bt);
|
||||||
notification_message(bt->notification, &sequence_display_on);
|
notification_message(bt->notification, &sequence_display_backlight_on);
|
||||||
string_t pin_str;
|
string_t pin_str;
|
||||||
dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64, 0, 0);
|
dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64, 0, 0);
|
||||||
string_init_printf(pin_str, "Verify code\n%06d", pin);
|
string_init_printf(pin_str, "Verify code\n%06d", pin);
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#include "cli_i.h"
|
#include "cli_i.h"
|
||||||
#include "cli_commands.h"
|
#include "cli_commands.h"
|
||||||
|
#include "cli_vcp.h"
|
||||||
#include <furi_hal_version.h>
|
#include <furi_hal_version.h>
|
||||||
#include <loader/loader.h>
|
#include <loader/loader.h>
|
||||||
|
|
||||||
|
#define TAG "CliSrv"
|
||||||
|
|
||||||
Cli* cli_alloc() {
|
Cli* cli_alloc() {
|
||||||
Cli* cli = malloc(sizeof(Cli));
|
Cli* cli = malloc(sizeof(Cli));
|
||||||
|
|
||||||
@@ -12,55 +14,78 @@ Cli* cli_alloc() {
|
|||||||
string_init(cli->last_line);
|
string_init(cli->last_line);
|
||||||
string_init(cli->line);
|
string_init(cli->line);
|
||||||
|
|
||||||
|
cli->session = NULL;
|
||||||
|
|
||||||
cli->mutex = osMutexNew(NULL);
|
cli->mutex = osMutexNew(NULL);
|
||||||
furi_check(cli->mutex);
|
furi_check(cli->mutex);
|
||||||
|
|
||||||
|
cli->idle_sem = osSemaphoreNew(1, 0, NULL);
|
||||||
|
|
||||||
return cli;
|
return cli;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_free(Cli* cli) {
|
void cli_putc(Cli* cli, char c) {
|
||||||
furi_assert(cli);
|
furi_assert(cli);
|
||||||
|
if(cli->session != NULL) {
|
||||||
string_clear(cli->last_line);
|
cli->session->tx((uint8_t*)&c, 1);
|
||||||
string_clear(cli->line);
|
}
|
||||||
|
|
||||||
CliCommandTree_clear(cli->commands);
|
|
||||||
|
|
||||||
free(cli);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cli_putc(char c) {
|
|
||||||
furi_hal_vcp_tx((uint8_t*)&c, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char cli_getc(Cli* cli) {
|
char cli_getc(Cli* cli) {
|
||||||
furi_assert(cli);
|
furi_assert(cli);
|
||||||
char c;
|
char c = 0;
|
||||||
if(furi_hal_vcp_rx((uint8_t*)&c, 1) == 0) {
|
if(cli->session != NULL) {
|
||||||
|
if(cli->session->rx((uint8_t*)&c, 1, osWaitForever) == 0) {
|
||||||
|
cli_reset(cli);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
cli_reset(cli);
|
cli_reset(cli);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_stdout_callback(void* _cookie, const char* data, size_t size) {
|
|
||||||
furi_hal_vcp_tx((const uint8_t*)data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cli_write(Cli* cli, const uint8_t* buffer, size_t size) {
|
void cli_write(Cli* cli, const uint8_t* buffer, size_t size) {
|
||||||
return furi_hal_vcp_tx(buffer, size);
|
furi_assert(cli);
|
||||||
|
if(cli->session != NULL) {
|
||||||
|
cli->session->tx(buffer, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cli_read(Cli* cli, uint8_t* buffer, size_t size) {
|
size_t cli_read(Cli* cli, uint8_t* buffer, size_t size) {
|
||||||
return furi_hal_vcp_rx(buffer, size);
|
furi_assert(cli);
|
||||||
|
if(cli->session != NULL) {
|
||||||
|
return cli->session->rx(buffer, size, osWaitForever);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cli_read_timeout(Cli* cli, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||||
|
furi_assert(cli);
|
||||||
|
if(cli->session != NULL) {
|
||||||
|
return cli->session->rx(buffer, size, timeout);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cli_cmd_interrupt_received(Cli* cli) {
|
bool cli_cmd_interrupt_received(Cli* cli) {
|
||||||
|
furi_assert(cli);
|
||||||
char c = '\0';
|
char c = '\0';
|
||||||
if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 0) == 1) {
|
if(cli->session != NULL) {
|
||||||
return c == CliSymbolAsciiETX;
|
if(cli->session->rx((uint8_t*)&c, 1, 0) == 1) {
|
||||||
} else {
|
return c == CliSymbolAsciiETX;
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cli_is_connected(Cli* cli) {
|
||||||
|
furi_assert(cli);
|
||||||
|
if(cli->session != NULL) {
|
||||||
|
return (cli->session->is_connected());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_print_usage(const char* cmd, const char* usage, const char* arg) {
|
void cli_print_usage(const char* cmd, const char* usage, const char* arg) {
|
||||||
@@ -139,7 +164,7 @@ static void cli_handle_backspace(Cli* cli) {
|
|||||||
|
|
||||||
cli->cursor_position--;
|
cli->cursor_position--;
|
||||||
} else {
|
} else {
|
||||||
cli_putc(CliSymbolAsciiBell);
|
cli_putc(cli, CliSymbolAsciiBell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +235,7 @@ static void cli_handle_enter(Cli* cli) {
|
|||||||
printf(
|
printf(
|
||||||
"`%s` command not found, use `help` or `?` to list all available commands",
|
"`%s` command not found, use `help` or `?` to list all available commands",
|
||||||
string_get_cstr(command));
|
string_get_cstr(command));
|
||||||
cli_putc(CliSymbolAsciiBell);
|
cli_putc(cli, CliSymbolAsciiBell);
|
||||||
}
|
}
|
||||||
furi_check(osMutexRelease(cli->mutex) == osOK);
|
furi_check(osMutexRelease(cli->mutex) == osOK);
|
||||||
|
|
||||||
@@ -301,43 +326,43 @@ static void cli_handle_escape(Cli* cli, char c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cli_process_input(Cli* cli) {
|
void cli_process_input(Cli* cli) {
|
||||||
char c = cli_getc(cli);
|
char in_chr = cli_getc(cli);
|
||||||
size_t r;
|
size_t rx_len;
|
||||||
|
|
||||||
if(c == CliSymbolAsciiTab) {
|
if(in_chr == CliSymbolAsciiTab) {
|
||||||
cli_handle_autocomplete(cli);
|
cli_handle_autocomplete(cli);
|
||||||
} else if(c == CliSymbolAsciiSOH) {
|
} else if(in_chr == CliSymbolAsciiSOH) {
|
||||||
osDelay(33); // We are too fast, Minicom is not ready yet
|
osDelay(33); // We are too fast, Minicom is not ready yet
|
||||||
cli_motd();
|
cli_motd();
|
||||||
cli_prompt(cli);
|
cli_prompt(cli);
|
||||||
} else if(c == CliSymbolAsciiETX) {
|
} else if(in_chr == CliSymbolAsciiETX) {
|
||||||
cli_reset(cli);
|
cli_reset(cli);
|
||||||
cli_prompt(cli);
|
cli_prompt(cli);
|
||||||
} else if(c == CliSymbolAsciiEOT) {
|
} else if(in_chr == CliSymbolAsciiEOT) {
|
||||||
cli_reset(cli);
|
cli_reset(cli);
|
||||||
} else if(c == CliSymbolAsciiEsc) {
|
} else if(in_chr == CliSymbolAsciiEsc) {
|
||||||
r = furi_hal_vcp_rx((uint8_t*)&c, 1);
|
rx_len = cli_read(cli, (uint8_t*)&in_chr, 1);
|
||||||
if(r && c == '[') {
|
if((rx_len > 0) && (in_chr == '[')) {
|
||||||
furi_hal_vcp_rx((uint8_t*)&c, 1);
|
cli_read(cli, (uint8_t*)&in_chr, 1);
|
||||||
cli_handle_escape(cli, c);
|
cli_handle_escape(cli, in_chr);
|
||||||
} else {
|
} else {
|
||||||
cli_putc(CliSymbolAsciiBell);
|
cli_putc(cli, CliSymbolAsciiBell);
|
||||||
}
|
}
|
||||||
} else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) {
|
} else if(in_chr == CliSymbolAsciiBackspace || in_chr == CliSymbolAsciiDel) {
|
||||||
cli_handle_backspace(cli);
|
cli_handle_backspace(cli);
|
||||||
} else if(c == CliSymbolAsciiCR) {
|
} else if(in_chr == CliSymbolAsciiCR) {
|
||||||
cli_handle_enter(cli);
|
cli_handle_enter(cli);
|
||||||
} else if(c >= 0x20 && c < 0x7F) {
|
} else if(in_chr >= 0x20 && in_chr < 0x7F) {
|
||||||
if(cli->cursor_position == string_size(cli->line)) {
|
if(cli->cursor_position == string_size(cli->line)) {
|
||||||
string_push_back(cli->line, c);
|
string_push_back(cli->line, in_chr);
|
||||||
cli_putc(c);
|
cli_putc(cli, in_chr);
|
||||||
} else {
|
} else {
|
||||||
// ToDo: better way?
|
// ToDo: better way?
|
||||||
string_t temp;
|
string_t temp;
|
||||||
string_init(temp);
|
string_init(temp);
|
||||||
string_reserve(temp, string_size(cli->line) + 1);
|
string_reserve(temp, string_size(cli->line) + 1);
|
||||||
string_set_strn(temp, string_get_cstr(cli->line), cli->cursor_position);
|
string_set_strn(temp, string_get_cstr(cli->line), cli->cursor_position);
|
||||||
string_push_back(temp, c);
|
string_push_back(temp, in_chr);
|
||||||
string_cat_str(temp, string_get_cstr(cli->line) + cli->cursor_position);
|
string_cat_str(temp, string_get_cstr(cli->line) + cli->cursor_position);
|
||||||
|
|
||||||
// cli->line is cleared and temp's buffer moved to cli->line
|
// cli->line is cleared and temp's buffer moved to cli->line
|
||||||
@@ -345,12 +370,12 @@ void cli_process_input(Cli* cli) {
|
|||||||
// NO MEMORY LEAK, STOP REPORTING IT
|
// NO MEMORY LEAK, STOP REPORTING IT
|
||||||
|
|
||||||
// Print character in replace mode
|
// Print character in replace mode
|
||||||
printf("\e[4h%c\e[4l", c);
|
printf("\e[4h%c\e[4l", in_chr);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
cli->cursor_position++;
|
cli->cursor_position++;
|
||||||
} else {
|
} else {
|
||||||
cli_putc(CliSymbolAsciiBell);
|
cli_putc(cli, CliSymbolAsciiBell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,19 +423,59 @@ void cli_delete_command(Cli* cli, const char* name) {
|
|||||||
string_clear(name_str);
|
string_clear(name_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cli_session_open(Cli* cli, void* session) {
|
||||||
|
furi_assert(cli);
|
||||||
|
|
||||||
|
furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK);
|
||||||
|
cli->session = session;
|
||||||
|
if(cli->session != NULL) {
|
||||||
|
cli->session->init();
|
||||||
|
furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout);
|
||||||
|
} else {
|
||||||
|
furi_stdglue_set_thread_stdout_callback(NULL);
|
||||||
|
}
|
||||||
|
osSemaphoreRelease(cli->idle_sem);
|
||||||
|
furi_check(osMutexRelease(cli->mutex) == osOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cli_session_close(Cli* cli) {
|
||||||
|
furi_assert(cli);
|
||||||
|
|
||||||
|
furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK);
|
||||||
|
if(cli->session != NULL) {
|
||||||
|
cli->session->deinit();
|
||||||
|
}
|
||||||
|
cli->session = NULL;
|
||||||
|
furi_stdglue_set_thread_stdout_callback(NULL);
|
||||||
|
furi_check(osMutexRelease(cli->mutex) == osOK);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t cli_srv(void* p) {
|
int32_t cli_srv(void* p) {
|
||||||
Cli* cli = cli_alloc();
|
Cli* cli = cli_alloc();
|
||||||
|
|
||||||
furi_hal_vcp_init();
|
|
||||||
|
|
||||||
// Init basic cli commands
|
// Init basic cli commands
|
||||||
cli_commands_init(cli);
|
cli_commands_init(cli);
|
||||||
|
|
||||||
furi_record_create("cli", cli);
|
furi_record_create("cli", cli);
|
||||||
|
|
||||||
furi_stdglue_set_thread_stdout_callback(cli_stdout_callback);
|
if(cli->session != NULL) {
|
||||||
|
furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout);
|
||||||
|
} else {
|
||||||
|
furi_stdglue_set_thread_stdout_callback(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(furi_hal_rtc_get_boot_mode() == FuriHalRtcBootModeNormal) {
|
||||||
|
cli_session_open(cli, &cli_vcp);
|
||||||
|
} else {
|
||||||
|
FURI_LOG_W(TAG, "Skipped CLI session open: device in special startup mode");
|
||||||
|
}
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
cli_process_input(cli);
|
if(cli->session != NULL) {
|
||||||
|
cli_process_input(cli);
|
||||||
|
} else {
|
||||||
|
furi_check(osSemaphoreAcquire(cli->idle_sem, osWaitForever) == osOK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -73,17 +73,28 @@ void cli_print_usage(const char* cmd, const char* usage, const char* arg);
|
|||||||
*/
|
*/
|
||||||
void cli_delete_command(Cli* cli, const char* name);
|
void cli_delete_command(Cli* cli, const char* name);
|
||||||
|
|
||||||
/** Read from terminal Do it only from inside of cli call.
|
/** Read from terminal
|
||||||
*
|
*
|
||||||
* @param cli Cli instance
|
* @param cli Cli instance
|
||||||
* @param buffer pointer to buffer
|
* @param buffer pointer to buffer
|
||||||
* @param size size of buffer in bytes
|
* @param size size of buffer in bytes
|
||||||
*
|
*
|
||||||
* @return bytes written
|
* @return bytes read
|
||||||
*/
|
*/
|
||||||
size_t cli_read(Cli* cli, uint8_t* buffer, size_t size);
|
size_t cli_read(Cli* cli, uint8_t* buffer, size_t size);
|
||||||
|
|
||||||
/** Not blocking check for interrupt command received
|
/** Non-blocking read from terminal
|
||||||
|
*
|
||||||
|
* @param cli Cli instance
|
||||||
|
* @param buffer pointer to buffer
|
||||||
|
* @param size size of buffer in bytes
|
||||||
|
* @param timeout timeout value in ms
|
||||||
|
*
|
||||||
|
* @return bytes read
|
||||||
|
*/
|
||||||
|
size_t cli_read_timeout(Cli* cli, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||||
|
|
||||||
|
/** Non-blocking check for interrupt command received
|
||||||
*
|
*
|
||||||
* @param cli Cli instance
|
* @param cli Cli instance
|
||||||
*
|
*
|
||||||
@@ -111,6 +122,12 @@ char cli_getc(Cli* cli);
|
|||||||
*/
|
*/
|
||||||
void cli_nl();
|
void cli_nl();
|
||||||
|
|
||||||
|
void cli_session_open(Cli* cli, void* session);
|
||||||
|
|
||||||
|
void cli_session_close(Cli* cli);
|
||||||
|
|
||||||
|
bool cli_is_connected(Cli* cli);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ void cli_command_led(Cli* cli, string_t args, void* context) {
|
|||||||
} else if(!string_cmp(light_name, "b")) {
|
} else if(!string_cmp(light_name, "b")) {
|
||||||
notification_led_message.type = NotificationMessageTypeLedBlue;
|
notification_led_message.type = NotificationMessageTypeLedBlue;
|
||||||
} else if(!string_cmp(light_name, "bl")) {
|
} else if(!string_cmp(light_name, "bl")) {
|
||||||
notification_led_message.type = NotificationMessageTypeLedDisplay;
|
notification_led_message.type = NotificationMessageTypeLedDisplayBacklight;
|
||||||
} else {
|
} else {
|
||||||
cli_print_usage("led", "<r|g|b|bl> <0-255>", string_get_cstr(args));
|
cli_print_usage("led", "<r|g|b|bl> <0-255>", string_get_cstr(args));
|
||||||
string_clear(light_name);
|
string_clear(light_name);
|
||||||
|
|||||||
@@ -18,6 +18,17 @@ typedef struct {
|
|||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
} CliCommand;
|
} CliCommand;
|
||||||
|
|
||||||
|
typedef struct CliSession CliSession;
|
||||||
|
|
||||||
|
struct CliSession {
|
||||||
|
void (*init)(void);
|
||||||
|
void (*deinit)(void);
|
||||||
|
size_t (*rx)(uint8_t* buffer, size_t size, uint32_t timeout);
|
||||||
|
void (*tx)(const uint8_t* buffer, size_t size);
|
||||||
|
void (*tx_stdout)(void* _cookie, const char* data, size_t size);
|
||||||
|
bool (*is_connected)(void);
|
||||||
|
};
|
||||||
|
|
||||||
BPTREE_DEF2(
|
BPTREE_DEF2(
|
||||||
CliCommandTree,
|
CliCommandTree,
|
||||||
CLI_COMMANDS_TREE_RANK,
|
CLI_COMMANDS_TREE_RANK,
|
||||||
@@ -31,18 +42,18 @@ BPTREE_DEF2(
|
|||||||
struct Cli {
|
struct Cli {
|
||||||
CliCommandTree_t commands;
|
CliCommandTree_t commands;
|
||||||
osMutexId_t mutex;
|
osMutexId_t mutex;
|
||||||
|
osSemaphoreId_t idle_sem;
|
||||||
string_t last_line;
|
string_t last_line;
|
||||||
string_t line;
|
string_t line;
|
||||||
|
CliSession* session;
|
||||||
|
|
||||||
size_t cursor_position;
|
size_t cursor_position;
|
||||||
};
|
};
|
||||||
|
|
||||||
Cli* cli_alloc();
|
Cli* cli_alloc();
|
||||||
|
|
||||||
void cli_free(Cli* cli);
|
|
||||||
|
|
||||||
void cli_reset(Cli* cli);
|
void cli_reset(Cli* cli);
|
||||||
|
|
||||||
void cli_putc(char c);
|
void cli_putc(Cli* cli, char c);
|
||||||
|
|
||||||
void cli_stdout_callback(void* _cookie, const char* data, size_t size);
|
void cli_stdout_callback(void* _cookie, const char* data, size_t size);
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <stream_buffer.h>
|
#include <stream_buffer.h>
|
||||||
|
#include "cli_i.h"
|
||||||
|
|
||||||
#define TAG "FuriHalVcp"
|
#define TAG "CliVcp"
|
||||||
|
|
||||||
#define USB_CDC_PKT_LEN CDC_DATA_SZ
|
#define USB_CDC_PKT_LEN CDC_DATA_SZ
|
||||||
#define VCP_RX_BUF_SIZE (USB_CDC_PKT_LEN * 3)
|
#define VCP_RX_BUF_SIZE (USB_CDC_PKT_LEN * 3)
|
||||||
@@ -12,19 +13,18 @@
|
|||||||
#define VCP_IF_NUM 0
|
#define VCP_IF_NUM 0
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VcpEvtEnable = (1 << 0),
|
VcpEvtStop = (1 << 0),
|
||||||
VcpEvtDisable = (1 << 1),
|
VcpEvtConnect = (1 << 1),
|
||||||
VcpEvtConnect = (1 << 2),
|
VcpEvtDisconnect = (1 << 2),
|
||||||
VcpEvtDisconnect = (1 << 3),
|
VcpEvtStreamRx = (1 << 3),
|
||||||
VcpEvtStreamRx = (1 << 4),
|
VcpEvtRx = (1 << 4),
|
||||||
VcpEvtRx = (1 << 5),
|
VcpEvtStreamTx = (1 << 5),
|
||||||
VcpEvtStreamTx = (1 << 6),
|
VcpEvtTx = (1 << 6),
|
||||||
VcpEvtTx = (1 << 7),
|
|
||||||
} WorkerEvtFlags;
|
} WorkerEvtFlags;
|
||||||
|
|
||||||
#define VCP_THREAD_FLAG_ALL \
|
#define VCP_THREAD_FLAG_ALL \
|
||||||
(VcpEvtEnable | VcpEvtDisable | VcpEvtConnect | VcpEvtDisconnect | VcpEvtRx | VcpEvtTx | \
|
(VcpEvtStop | VcpEvtConnect | VcpEvtDisconnect | VcpEvtRx | VcpEvtTx | VcpEvtStreamRx | \
|
||||||
VcpEvtStreamRx | VcpEvtStreamTx)
|
VcpEvtStreamTx)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
@@ -33,9 +33,12 @@ typedef struct {
|
|||||||
StreamBufferHandle_t rx_stream;
|
StreamBufferHandle_t rx_stream;
|
||||||
|
|
||||||
volatile bool connected;
|
volatile bool connected;
|
||||||
|
volatile bool running;
|
||||||
|
|
||||||
|
FuriHalUsbInterface* usb_if_prev;
|
||||||
|
|
||||||
uint8_t data_buffer[USB_CDC_PKT_LEN];
|
uint8_t data_buffer[USB_CDC_PKT_LEN];
|
||||||
} FuriHalVcp;
|
} CliVcp;
|
||||||
|
|
||||||
static int32_t vcp_worker(void* context);
|
static int32_t vcp_worker(void* context);
|
||||||
static void vcp_on_cdc_tx_complete(void* context);
|
static void vcp_on_cdc_tx_complete(void* context);
|
||||||
@@ -51,25 +54,23 @@ static CdcCallbacks cdc_cb = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static FuriHalVcp* vcp = NULL;
|
static CliVcp* vcp = NULL;
|
||||||
|
|
||||||
static const uint8_t ascii_soh = 0x01;
|
static const uint8_t ascii_soh = 0x01;
|
||||||
static const uint8_t ascii_eot = 0x04;
|
static const uint8_t ascii_eot = 0x04;
|
||||||
|
|
||||||
void furi_hal_vcp_init() {
|
static void cli_vcp_init() {
|
||||||
vcp = malloc(sizeof(FuriHalVcp));
|
if(vcp == NULL) {
|
||||||
|
vcp = malloc(sizeof(CliVcp));
|
||||||
|
vcp->tx_stream = xStreamBufferCreate(VCP_TX_BUF_SIZE, 1);
|
||||||
|
vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1);
|
||||||
|
}
|
||||||
|
furi_assert(vcp->thread == NULL);
|
||||||
|
|
||||||
vcp->connected = false;
|
vcp->connected = false;
|
||||||
|
|
||||||
vcp->tx_stream = xStreamBufferCreate(VCP_TX_BUF_SIZE, 1);
|
|
||||||
vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1);
|
|
||||||
|
|
||||||
if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
|
|
||||||
FURI_LOG_W(TAG, "Skipped worker init: device in special startup mode");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vcp->thread = furi_thread_alloc();
|
vcp->thread = furi_thread_alloc();
|
||||||
furi_thread_set_name(vcp->thread, "VcpDriver");
|
furi_thread_set_name(vcp->thread, "CliVcpWorker");
|
||||||
furi_thread_set_stack_size(vcp->thread, 1024);
|
furi_thread_set_stack_size(vcp->thread, 1024);
|
||||||
furi_thread_set_callback(vcp->thread, vcp_worker);
|
furi_thread_set_callback(vcp->thread, vcp_worker);
|
||||||
furi_thread_start(vcp->thread);
|
furi_thread_start(vcp->thread);
|
||||||
@@ -77,48 +78,35 @@ void furi_hal_vcp_init() {
|
|||||||
FURI_LOG_I(TAG, "Init OK");
|
FURI_LOG_I(TAG, "Init OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cli_vcp_deinit() {
|
||||||
|
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStop);
|
||||||
|
furi_thread_join(vcp->thread);
|
||||||
|
furi_thread_free(vcp->thread);
|
||||||
|
vcp->thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t vcp_worker(void* context) {
|
static int32_t vcp_worker(void* context) {
|
||||||
bool enabled = true;
|
bool tx_idle = true;
|
||||||
bool tx_idle = false;
|
|
||||||
size_t missed_rx = 0;
|
size_t missed_rx = 0;
|
||||||
uint8_t last_tx_pkt_len = 0;
|
uint8_t last_tx_pkt_len = 0;
|
||||||
|
|
||||||
furi_hal_usb_set_config(&usb_cdc_single, NULL);
|
// Switch USB to VCP mode (if it is not set yet)
|
||||||
|
vcp->usb_if_prev = furi_hal_usb_get_config();
|
||||||
|
if((vcp->usb_if_prev != &usb_cdc_single) && (vcp->usb_if_prev != &usb_cdc_dual)) {
|
||||||
|
furi_hal_usb_set_config(&usb_cdc_single, NULL);
|
||||||
|
}
|
||||||
furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL);
|
furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "Start");
|
||||||
|
vcp->running = true;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
uint32_t flags = osThreadFlagsWait(VCP_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
uint32_t flags = osThreadFlagsWait(VCP_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||||
furi_assert((flags & osFlagsError) == 0);
|
furi_assert((flags & osFlagsError) == 0);
|
||||||
|
|
||||||
// VCP enabled
|
|
||||||
if((flags & VcpEvtEnable) && !enabled) {
|
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
|
||||||
FURI_LOG_D(TAG, "Enable");
|
|
||||||
#endif
|
|
||||||
flags |= VcpEvtTx;
|
|
||||||
furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL);
|
|
||||||
enabled = true;
|
|
||||||
furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN); // flush Rx buffer
|
|
||||||
if(furi_hal_cdc_get_ctrl_line_state(VCP_IF_NUM) & (1 << 0)) {
|
|
||||||
vcp->connected = true;
|
|
||||||
xStreamBufferSend(vcp->rx_stream, &ascii_soh, 1, osWaitForever);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// VCP disabled
|
|
||||||
if((flags & VcpEvtDisable) && enabled) {
|
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
|
||||||
FURI_LOG_D(TAG, "Disable");
|
|
||||||
#endif
|
|
||||||
enabled = false;
|
|
||||||
vcp->connected = false;
|
|
||||||
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
|
||||||
xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, osWaitForever);
|
|
||||||
}
|
|
||||||
|
|
||||||
// VCP session opened
|
// VCP session opened
|
||||||
if((flags & VcpEvtConnect) && enabled) {
|
if(flags & VcpEvtConnect) {
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "Connect");
|
FURI_LOG_D(TAG, "Connect");
|
||||||
#endif
|
#endif
|
||||||
if(vcp->connected == false) {
|
if(vcp->connected == false) {
|
||||||
@@ -128,8 +116,8 @@ static int32_t vcp_worker(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VCP session closed
|
// VCP session closed
|
||||||
if((flags & VcpEvtDisconnect) && enabled) {
|
if(flags & VcpEvtDisconnect) {
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "Disconnect");
|
FURI_LOG_D(TAG, "Disconnect");
|
||||||
#endif
|
#endif
|
||||||
if(vcp->connected == true) {
|
if(vcp->connected == true) {
|
||||||
@@ -140,8 +128,8 @@ static int32_t vcp_worker(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rx buffer was read, maybe there is enough space for new data?
|
// Rx buffer was read, maybe there is enough space for new data?
|
||||||
if((flags & VcpEvtStreamRx) && enabled && missed_rx > 0) {
|
if((flags & VcpEvtStreamRx) && (missed_rx > 0)) {
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "StreamRx");
|
FURI_LOG_D(TAG, "StreamRx");
|
||||||
#endif
|
#endif
|
||||||
if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
||||||
@@ -151,10 +139,10 @@ static int32_t vcp_worker(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New data received
|
// New data received
|
||||||
if((flags & VcpEvtRx)) {
|
if(flags & VcpEvtRx) {
|
||||||
if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
||||||
int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN);
|
int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN);
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "Rx %d", len);
|
FURI_LOG_D(TAG, "Rx %d", len);
|
||||||
#endif
|
#endif
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
@@ -163,7 +151,7 @@ static int32_t vcp_worker(void* context) {
|
|||||||
len);
|
len);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "Rx missed");
|
FURI_LOG_D(TAG, "Rx missed");
|
||||||
#endif
|
#endif
|
||||||
missed_rx++;
|
missed_rx++;
|
||||||
@@ -171,8 +159,8 @@ static int32_t vcp_worker(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New data in Tx buffer
|
// New data in Tx buffer
|
||||||
if((flags & VcpEvtStreamTx) && enabled) {
|
if(flags & VcpEvtStreamTx) {
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "StreamTx");
|
FURI_LOG_D(TAG, "StreamTx");
|
||||||
#endif
|
#endif
|
||||||
if(tx_idle) {
|
if(tx_idle) {
|
||||||
@@ -181,10 +169,10 @@ static int32_t vcp_worker(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CDC write transfer done
|
// CDC write transfer done
|
||||||
if((flags & VcpEvtTx) && enabled) {
|
if(flags & VcpEvtTx) {
|
||||||
size_t len =
|
size_t len =
|
||||||
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "Tx %d", len);
|
FURI_LOG_D(TAG, "Tx %d", len);
|
||||||
#endif
|
#endif
|
||||||
if(len > 0) { // Some data left in Tx buffer. Sending it now
|
if(len > 0) { // Some data left in Tx buffer. Sending it now
|
||||||
@@ -202,23 +190,33 @@ static int32_t vcp_worker(void* context) {
|
|||||||
last_tx_pkt_len = 0;
|
last_tx_pkt_len = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(flags & VcpEvtStop) {
|
||||||
|
vcp->connected = false;
|
||||||
|
vcp->running = false;
|
||||||
|
furi_hal_cdc_set_callbacks(VCP_IF_NUM, NULL, NULL);
|
||||||
|
// Restore previous USB mode (if it was set during init)
|
||||||
|
if((vcp->usb_if_prev != &usb_cdc_single) && (vcp->usb_if_prev != &usb_cdc_dual)) {
|
||||||
|
furi_hal_usb_set_config(vcp->usb_if_prev, NULL);
|
||||||
|
}
|
||||||
|
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
||||||
|
xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, osWaitForever);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
FURI_LOG_D(TAG, "End");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_vcp_enable() {
|
static size_t cli_vcp_rx(uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtEnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_vcp_disable() {
|
|
||||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisable);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout) {
|
|
||||||
furi_assert(vcp);
|
furi_assert(vcp);
|
||||||
furi_assert(buffer);
|
furi_assert(buffer);
|
||||||
|
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
if(vcp->running == false) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "rx %u start", size);
|
FURI_LOG_D(TAG, "rx %u start", size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -229,7 +227,7 @@ size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeo
|
|||||||
if(batch_size > VCP_RX_BUF_SIZE) batch_size = VCP_RX_BUF_SIZE;
|
if(batch_size > VCP_RX_BUF_SIZE) batch_size = VCP_RX_BUF_SIZE;
|
||||||
|
|
||||||
size_t len = xStreamBufferReceive(vcp->rx_stream, buffer, batch_size, timeout);
|
size_t len = xStreamBufferReceive(vcp->rx_stream, buffer, batch_size, timeout);
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "rx %u ", batch_size);
|
FURI_LOG_D(TAG, "rx %u ", batch_size);
|
||||||
#endif
|
#endif
|
||||||
if(len == 0) break;
|
if(len == 0) break;
|
||||||
@@ -239,22 +237,21 @@ size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeo
|
|||||||
rx_cnt += len;
|
rx_cnt += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "rx %u end", size);
|
FURI_LOG_D(TAG, "rx %u end", size);
|
||||||
#endif
|
#endif
|
||||||
return rx_cnt;
|
return rx_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) {
|
static void cli_vcp_tx(const uint8_t* buffer, size_t size) {
|
||||||
furi_assert(vcp);
|
|
||||||
return furi_hal_vcp_rx_with_timeout(buffer, size, osWaitForever);
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) {
|
|
||||||
furi_assert(vcp);
|
furi_assert(vcp);
|
||||||
furi_assert(buffer);
|
furi_assert(buffer);
|
||||||
|
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
if(vcp->running == false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "tx %u start", size);
|
FURI_LOG_D(TAG, "tx %u start", size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -264,7 +261,7 @@ void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) {
|
|||||||
|
|
||||||
xStreamBufferSend(vcp->tx_stream, buffer, batch_size, osWaitForever);
|
xStreamBufferSend(vcp->tx_stream, buffer, batch_size, osWaitForever);
|
||||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamTx);
|
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamTx);
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "tx %u", batch_size);
|
FURI_LOG_D(TAG, "tx %u", batch_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -272,11 +269,15 @@ void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) {
|
|||||||
buffer += batch_size;
|
buffer += batch_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FURI_HAL_USB_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "tx %u end", size);
|
FURI_LOG_D(TAG, "tx %u end", size);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) {
|
||||||
|
cli_vcp_tx((const uint8_t*)data, size);
|
||||||
|
}
|
||||||
|
|
||||||
static void vcp_state_callback(void* context, uint8_t state) {
|
static void vcp_state_callback(void* context, uint8_t state) {
|
||||||
if(state == 0) {
|
if(state == 0) {
|
||||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect);
|
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect);
|
||||||
@@ -303,7 +304,16 @@ static void vcp_on_cdc_tx_complete(void* context) {
|
|||||||
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx);
|
osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool furi_hal_vcp_is_connected(void) {
|
static bool cli_vcp_is_connected(void) {
|
||||||
furi_assert(vcp);
|
furi_assert(vcp);
|
||||||
return vcp->connected;
|
return vcp->connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CliSession cli_vcp = {
|
||||||
|
cli_vcp_init,
|
||||||
|
cli_vcp_deinit,
|
||||||
|
cli_vcp_rx,
|
||||||
|
cli_vcp_tx,
|
||||||
|
cli_vcp_tx_stdout,
|
||||||
|
cli_vcp_is_connected,
|
||||||
|
};
|
||||||
18
applications/cli/cli_vcp.h
Normal file
18
applications/cli/cli_vcp.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @file cli_vcp.h
|
||||||
|
* VCP HAL API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cli_i.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern CliSession cli_vcp;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -45,7 +45,7 @@ typedef enum {
|
|||||||
#define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx)
|
#define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx)
|
||||||
|
|
||||||
const NotificationSequence sequence_notification = {
|
const NotificationSequence sequence_notification = {
|
||||||
&message_display_on,
|
&message_display_backlight_on,
|
||||||
&message_green_255,
|
&message_green_255,
|
||||||
&message_delay_10,
|
&message_delay_10,
|
||||||
NULL,
|
NULL,
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ void desktop_lock(Desktop* desktop) {
|
|||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
||||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
||||||
notification_message(desktop->notification, &sequence_display_off_delay_1000);
|
notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_unlock(Desktop* desktop) {
|
void desktop_unlock(Desktop* desktop) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <toolbox/saved_struct.h>
|
#include <toolbox/saved_struct.h>
|
||||||
|
|
||||||
#define DESKTOP_SETTINGS_VER (2)
|
#define DESKTOP_SETTINGS_VER (3)
|
||||||
#define DESKTOP_SETTINGS_PATH "/int/desktop.settings"
|
#define DESKTOP_SETTINGS_PATH "/int/desktop.settings"
|
||||||
#define DESKTOP_SETTINGS_MAGIC (0x17)
|
#define DESKTOP_SETTINGS_MAGIC (0x17)
|
||||||
#define PIN_MAX_LENGTH 12
|
#define PIN_MAX_LENGTH 12
|
||||||
@@ -39,5 +39,6 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t favorite;
|
uint16_t favorite;
|
||||||
PinCode pin_code;
|
PinCode pin_code;
|
||||||
|
uint8_t is_locked;
|
||||||
uint32_t auto_lock_delay_ms;
|
uint32_t auto_lock_delay_ms;
|
||||||
} DesktopSettings;
|
} DesktopSettings;
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
|
|
||||||
#include "../helpers/pin_lock.h"
|
#include "../helpers/pin_lock.h"
|
||||||
#include "../desktop_i.h"
|
#include "../desktop_i.h"
|
||||||
|
#include <cli/cli_vcp.h>
|
||||||
|
|
||||||
static const NotificationSequence sequence_pin_fail = {
|
static const NotificationSequence sequence_pin_fail = {
|
||||||
&message_display_on,
|
&message_display_backlight_on,
|
||||||
|
|
||||||
&message_red_255,
|
&message_red_255,
|
||||||
&message_vibro_on,
|
&message_vibro_on,
|
||||||
@@ -61,26 +62,50 @@ uint32_t desktop_pin_lock_get_fail_timeout() {
|
|||||||
return pin_timeout;
|
return pin_timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_pin_lock() {
|
void desktop_pin_lock(DesktopSettings* settings) {
|
||||||
|
furi_assert(settings);
|
||||||
|
|
||||||
furi_hal_rtc_set_pin_fails(0);
|
furi_hal_rtc_set_pin_fails(0);
|
||||||
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
|
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
|
||||||
furi_hal_usb_disable();
|
Cli* cli = furi_record_open("cli");
|
||||||
|
cli_session_close(cli);
|
||||||
|
furi_record_close("cli");
|
||||||
|
settings->is_locked = 1;
|
||||||
|
SAVE_DESKTOP_SETTINGS(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_pin_unlock() {
|
void desktop_pin_unlock(DesktopSettings* settings) {
|
||||||
|
furi_assert(settings);
|
||||||
|
|
||||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
||||||
furi_hal_usb_enable();
|
Cli* cli = furi_record_open("cli");
|
||||||
|
cli_session_open(cli, &cli_vcp);
|
||||||
|
furi_record_close("cli");
|
||||||
|
settings->is_locked = 0;
|
||||||
|
SAVE_DESKTOP_SETTINGS(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void desktop_pin_lock_init(DesktopSettings* settings) {
|
void desktop_pin_lock_init(DesktopSettings* settings) {
|
||||||
|
furi_assert(settings);
|
||||||
|
|
||||||
if(settings->pin_code.length > 0) {
|
if(settings->pin_code.length > 0) {
|
||||||
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
|
if(settings->is_locked == 1) {
|
||||||
furi_hal_usb_disable();
|
furi_hal_rtc_set_flag(FuriHalRtcFlagLock);
|
||||||
|
} else {
|
||||||
|
if(desktop_pin_lock_is_locked()) {
|
||||||
|
settings->is_locked = 1;
|
||||||
|
SAVE_DESKTOP_SETTINGS(settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
furi_hal_rtc_set_pin_fails(0);
|
furi_hal_rtc_set_pin_fails(0);
|
||||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
||||||
furi_hal_usb_enable();
|
furi_hal_usb_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(desktop_pin_lock_is_locked()) {
|
||||||
|
furi_hal_usb_disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool desktop_pin_lock_verify(const PinCode* pin_set, const PinCode* pin_entered) {
|
bool desktop_pin_lock_verify(const PinCode* pin_set, const PinCode* pin_entered) {
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ void desktop_pin_lock_error_notify();
|
|||||||
|
|
||||||
uint32_t desktop_pin_lock_get_fail_timeout();
|
uint32_t desktop_pin_lock_get_fail_timeout();
|
||||||
|
|
||||||
void desktop_pin_lock();
|
void desktop_pin_lock(DesktopSettings* settings);
|
||||||
|
|
||||||
void desktop_pin_unlock();
|
void desktop_pin_unlock(DesktopSettings* settings);
|
||||||
|
|
||||||
bool desktop_pin_lock_is_locked();
|
bool desktop_pin_lock_is_locked();
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
|
|||||||
break;
|
break;
|
||||||
case DesktopLockMenuEventPinLock:
|
case DesktopLockMenuEventPinLock:
|
||||||
if(desktop->settings.pin_code.length > 0) {
|
if(desktop->settings.pin_code.length > 0) {
|
||||||
desktop_pin_lock();
|
desktop_pin_lock(&desktop->settings);
|
||||||
desktop_lock(desktop);
|
desktop_lock(desktop);
|
||||||
} else {
|
} else {
|
||||||
LoaderStatus status =
|
LoaderStatus status =
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
|
|||||||
break;
|
break;
|
||||||
case DesktopLockedEventUpdate:
|
case DesktopLockedEventUpdate:
|
||||||
if(desktop_view_locked_is_locked_hint_visible(desktop->locked_view)) {
|
if(desktop_view_locked_is_locked_hint_visible(desktop->locked_view)) {
|
||||||
notification_message(desktop->notification, &sequence_display_off);
|
notification_message(desktop->notification, &sequence_display_backlight_off);
|
||||||
}
|
}
|
||||||
desktop_view_locked_update(desktop->locked_view);
|
desktop_view_locked_update(desktop->locked_view);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
|||||||
@@ -126,14 +126,14 @@ bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) {
|
|||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case DesktopPinInputEventUnlocked:
|
case DesktopPinInputEventUnlocked:
|
||||||
desktop_pin_unlock();
|
desktop_pin_unlock(&desktop->settings);
|
||||||
desktop_unlock(desktop);
|
desktop_unlock(desktop);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case DesktopPinInputEventBack:
|
case DesktopPinInputEventBack:
|
||||||
scene_manager_search_and_switch_to_previous_scene(
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
desktop->scene_manager, DesktopSceneLocked);
|
desktop->scene_manager, DesktopSceneLocked);
|
||||||
notification_message(desktop->notification, &sequence_display_off);
|
notification_message(desktop->notification, &sequence_display_backlight_off);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) {
|
|||||||
dolphin_deed_get_app_limit(app) - dolphin_state->data.icounter_daily_limit[app];
|
dolphin_deed_get_app_limit(app) - dolphin_state->data.icounter_daily_limit[app];
|
||||||
uint8_t deed_weight = CLAMP(dolphin_deed_get_weight(deed), weight_limit, 0);
|
uint8_t deed_weight = CLAMP(dolphin_deed_get_weight(deed), weight_limit, 0);
|
||||||
|
|
||||||
uint8_t xp_to_levelup = dolphin_state_xp_to_levelup(dolphin_state->data.icounter);
|
uint32_t xp_to_levelup = dolphin_state_xp_to_levelup(dolphin_state->data.icounter);
|
||||||
if(xp_to_levelup) {
|
if(xp_to_levelup) {
|
||||||
deed_weight = MIN(xp_to_levelup, deed_weight);
|
deed_weight = MIN(xp_to_levelup, deed_weight);
|
||||||
dolphin_state->data.icounter += deed_weight;
|
dolphin_state->data.icounter += deed_weight;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ void gpio_scene_usb_uart_on_enter(void* context) {
|
|||||||
gpio_usb_uart_set_callback(app->gpio_usb_uart, gpio_scene_usb_uart_callback, app);
|
gpio_usb_uart_set_callback(app->gpio_usb_uart, gpio_scene_usb_uart_callback, app);
|
||||||
scene_manager_set_scene_state(app->scene_manager, GpioSceneUsbUart, 0);
|
scene_manager_set_scene_state(app->scene_manager, GpioSceneUsbUart, 0);
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewUsbUart);
|
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewUsbUart);
|
||||||
notification_message(app->notifications, &sequence_display_lock);
|
notification_message(app->notifications, &sequence_display_backlight_enforce_on);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gpio_scene_usb_uart_on_event(void* context, SceneManagerEvent event) {
|
bool gpio_scene_usb_uart_on_event(void* context, SceneManagerEvent event) {
|
||||||
@@ -63,5 +63,5 @@ void gpio_scene_usb_uart_on_exit(void* context) {
|
|||||||
usb_uart_disable(app->usb_uart_bridge);
|
usb_uart_disable(app->usb_uart_bridge);
|
||||||
free(scene_usb_uart);
|
free(scene_usb_uart);
|
||||||
}
|
}
|
||||||
notification_message(app->notifications, &sequence_display_unlock);
|
notification_message(app->notifications, &sequence_display_backlight_enforce_auto);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <stream_buffer.h>
|
#include <stream_buffer.h>
|
||||||
#include <furi_hal_usb_cdc_i.h>
|
#include <furi_hal_usb_cdc_i.h>
|
||||||
#include "usb_cdc.h"
|
#include "usb_cdc.h"
|
||||||
|
#include "cli/cli_vcp.h"
|
||||||
|
#include "cli/cli.h"
|
||||||
|
|
||||||
#define USB_CDC_PKT_LEN CDC_DATA_SZ
|
#define USB_CDC_PKT_LEN CDC_DATA_SZ
|
||||||
#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)
|
#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)
|
||||||
@@ -16,17 +18,16 @@ static const GpioPin* flow_pins[][2] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WorkerEvtReserved = (1 << 0), // Reserved for StreamBuffer internal event
|
WorkerEvtStop = (1 << 0),
|
||||||
WorkerEvtStop = (1 << 1),
|
WorkerEvtRxDone = (1 << 1),
|
||||||
WorkerEvtRxDone = (1 << 2),
|
|
||||||
|
|
||||||
WorkerEvtTxStop = (1 << 3),
|
WorkerEvtTxStop = (1 << 2),
|
||||||
WorkerEvtCdcRx = (1 << 4),
|
WorkerEvtCdcRx = (1 << 3),
|
||||||
|
|
||||||
WorkerEvtCfgChange = (1 << 5),
|
WorkerEvtCfgChange = (1 << 4),
|
||||||
|
|
||||||
WorkerEvtLineCfgSet = (1 << 6),
|
WorkerEvtLineCfgSet = (1 << 5),
|
||||||
WorkerEvtCtrlLineSet = (1 << 7),
|
WorkerEvtCtrlLineSet = (1 << 6),
|
||||||
|
|
||||||
} WorkerEvtFlags;
|
} WorkerEvtFlags;
|
||||||
|
|
||||||
@@ -84,18 +85,29 @@ static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
|||||||
|
|
||||||
static void usb_uart_vcp_init(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
|
static void usb_uart_vcp_init(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
|
||||||
furi_hal_usb_unlock();
|
furi_hal_usb_unlock();
|
||||||
|
FURI_LOG_I("", "Init %d", vcp_ch);
|
||||||
if(vcp_ch == 0) {
|
if(vcp_ch == 0) {
|
||||||
|
Cli* cli = furi_record_open("cli");
|
||||||
|
cli_session_close(cli);
|
||||||
|
furi_record_close("cli");
|
||||||
furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true);
|
furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true);
|
||||||
furi_hal_vcp_disable();
|
|
||||||
} else {
|
} else {
|
||||||
furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true);
|
furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true);
|
||||||
|
Cli* cli = furi_record_open("cli");
|
||||||
|
cli_session_open(cli, &cli_vcp);
|
||||||
|
furi_record_close("cli");
|
||||||
}
|
}
|
||||||
furi_hal_cdc_set_callbacks(vcp_ch, (CdcCallbacks*)&cdc_cb, usb_uart);
|
furi_hal_cdc_set_callbacks(vcp_ch, (CdcCallbacks*)&cdc_cb, usb_uart);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
|
static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
|
||||||
furi_hal_cdc_set_callbacks(vcp_ch, NULL, NULL);
|
furi_hal_cdc_set_callbacks(vcp_ch, NULL, NULL);
|
||||||
if(vcp_ch == 0) furi_hal_vcp_enable();
|
FURI_LOG_I("", "Deinit %d", vcp_ch);
|
||||||
|
if(vcp_ch != 0) {
|
||||||
|
Cli* cli = furi_record_open("cli");
|
||||||
|
cli_session_close(cli);
|
||||||
|
furi_record_close("cli");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_uart_serial_init(UsbUartBridge* usb_uart, uint8_t uart_ch) {
|
static void usb_uart_serial_init(UsbUartBridge* usb_uart, uint8_t uart_ch) {
|
||||||
@@ -155,7 +167,6 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
furi_thread_set_context(usb_uart->tx_thread, usb_uart);
|
furi_thread_set_context(usb_uart->tx_thread, usb_uart);
|
||||||
furi_thread_set_callback(usb_uart->tx_thread, usb_uart_tx_thread);
|
furi_thread_set_callback(usb_uart->tx_thread, usb_uart_tx_thread);
|
||||||
|
|
||||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
|
||||||
usb_uart_vcp_init(usb_uart, usb_uart->cfg.vcp_ch);
|
usb_uart_vcp_init(usb_uart, usb_uart->cfg.vcp_ch);
|
||||||
usb_uart_serial_init(usb_uart, usb_uart->cfg.uart_ch);
|
usb_uart_serial_init(usb_uart, usb_uart->cfg.uart_ch);
|
||||||
usb_uart_set_baudrate(usb_uart, usb_uart->cfg.baudrate);
|
usb_uart_set_baudrate(usb_uart, usb_uart->cfg.baudrate);
|
||||||
@@ -247,11 +258,9 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
usb_uart_update_ctrl_lines(usb_uart);
|
usb_uart_update_ctrl_lines(usb_uart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch);
|
usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch);
|
||||||
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
|
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
|
||||||
furi_hal_usb_unlock();
|
|
||||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
|
||||||
if(usb_uart->cfg.flow_pins != 0) {
|
if(usb_uart->cfg.flow_pins != 0) {
|
||||||
furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog);
|
furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog);
|
||||||
furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog);
|
furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog);
|
||||||
@@ -265,6 +274,12 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
osMutexDelete(usb_uart->usb_mutex);
|
osMutexDelete(usb_uart->usb_mutex);
|
||||||
osSemaphoreDelete(usb_uart->tx_sem);
|
osSemaphoreDelete(usb_uart->tx_sem);
|
||||||
|
|
||||||
|
furi_hal_usb_unlock();
|
||||||
|
furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true);
|
||||||
|
Cli* cli = furi_record_open("cli");
|
||||||
|
cli_session_open(cli, &cli_vcp);
|
||||||
|
furi_record_close("cli");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ const CanvasFontParameters canvas_font_params[FontTotalNumber] = {
|
|||||||
Canvas* canvas_init() {
|
Canvas* canvas_init() {
|
||||||
Canvas* canvas = malloc(sizeof(Canvas));
|
Canvas* canvas = malloc(sizeof(Canvas));
|
||||||
|
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
|
|
||||||
// Setup u8g2
|
// Setup u8g2
|
||||||
u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
|
u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
|
||||||
canvas->orientation = CanvasOrientationHorizontal;
|
canvas->orientation = CanvasOrientationHorizontal;
|
||||||
@@ -31,8 +29,6 @@ Canvas* canvas_init() {
|
|||||||
canvas_clear(canvas);
|
canvas_clear(canvas);
|
||||||
canvas_commit(canvas);
|
canvas_commit(canvas);
|
||||||
|
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
|
|
||||||
return canvas;
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ iButtonApp::iButtonApp()
|
|||||||
: notification{"notification"}
|
: notification{"notification"}
|
||||||
, storage{"storage"}
|
, storage{"storage"}
|
||||||
, dialogs{"dialogs"} {
|
, dialogs{"dialogs"} {
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
key = ibutton_key_alloc();
|
key = ibutton_key_alloc();
|
||||||
key_worker = ibutton_worker_alloc();
|
key_worker = ibutton_worker_alloc();
|
||||||
ibutton_worker_start_thread(key_worker);
|
ibutton_worker_start_thread(key_worker);
|
||||||
@@ -56,8 +55,6 @@ iButtonApp::~iButtonApp() {
|
|||||||
ibutton_worker_stop_thread(key_worker);
|
ibutton_worker_stop_thread(key_worker);
|
||||||
ibutton_worker_free(key_worker);
|
ibutton_worker_free(key_worker);
|
||||||
ibutton_key_free(key);
|
ibutton_key_free(key);
|
||||||
|
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iButtonAppViewManager* iButtonApp::get_view_manager() {
|
iButtonAppViewManager* iButtonApp::get_view_manager() {
|
||||||
@@ -342,4 +339,4 @@ void iButtonApp::make_app_folder() {
|
|||||||
if(!storage_simply_mkdir(storage, app_folder)) {
|
if(!storage_simply_mkdir(storage, app_folder)) {
|
||||||
dialog_message_show_storage_error(dialogs, "Cannot create\napp folder");
|
dialog_message_show_storage_error(dialogs, "Cannot create\napp folder");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,11 +31,9 @@ LfRfidApp::LfRfidApp()
|
|||||||
, storage{"storage"}
|
, storage{"storage"}
|
||||||
, dialogs{"dialogs"}
|
, dialogs{"dialogs"}
|
||||||
, text_store(40) {
|
, text_store(40) {
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LfRfidApp::~LfRfidApp() {
|
LfRfidApp::~LfRfidApp() {
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LfRfidApp::run(void* _args) {
|
void LfRfidApp::run(void* _args) {
|
||||||
@@ -201,4 +199,4 @@ void LfRfidApp::make_app_folder() {
|
|||||||
if(!storage_simply_mkdir(storage, app_folder)) {
|
if(!storage_simply_mkdir(storage, app_folder)) {
|
||||||
dialog_message_show_storage_error(dialogs, "Cannot create\napp folder");
|
dialog_message_show_storage_error(dialogs, "Cannot create\napp folder");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,7 +238,10 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con
|
|||||||
if(thread_state == FuriThreadStateRunning) {
|
if(thread_state == FuriThreadStateRunning) {
|
||||||
event.type = LoaderEventTypeApplicationStarted;
|
event.type = LoaderEventTypeApplicationStarted;
|
||||||
furi_pubsub_publish(loader_instance->pubsub, &event);
|
furi_pubsub_publish(loader_instance->pubsub, &event);
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
|
if(!loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe) {
|
||||||
|
furi_hal_power_insomnia_enter();
|
||||||
|
}
|
||||||
} else if(thread_state == FuriThreadStateStopped) {
|
} else if(thread_state == FuriThreadStateStopped) {
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
TAG,
|
TAG,
|
||||||
@@ -251,7 +254,9 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con
|
|||||||
loader_instance->application_arguments = NULL;
|
loader_instance->application_arguments = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_hal_power_insomnia_exit();
|
if(!loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe) {
|
||||||
|
furi_hal_power_insomnia_exit();
|
||||||
|
}
|
||||||
loader_unlock(instance);
|
loader_unlock(instance);
|
||||||
|
|
||||||
event.type = LoaderEventTypeApplicationStopped;
|
event.type = LoaderEventTypeApplicationStopped;
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) {
|
|||||||
int32_t nfc_worker_task(void* context) {
|
int32_t nfc_worker_task(void* context) {
|
||||||
NfcWorker* nfc_worker = context;
|
NfcWorker* nfc_worker = context;
|
||||||
|
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
furi_hal_nfc_exit_sleep();
|
furi_hal_nfc_exit_sleep();
|
||||||
|
|
||||||
if(nfc_worker->state == NfcWorkerStateDetect) {
|
if(nfc_worker->state == NfcWorkerStateDetect) {
|
||||||
@@ -110,7 +109,6 @@ int32_t nfc_worker_task(void* context) {
|
|||||||
}
|
}
|
||||||
furi_hal_nfc_sleep();
|
furi_hal_nfc_sleep();
|
||||||
nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
|
nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ typedef enum {
|
|||||||
|
|
||||||
NotificationMessageTypeDelay,
|
NotificationMessageTypeDelay,
|
||||||
|
|
||||||
NotificationMessageTypeLedDisplay,
|
NotificationMessageTypeLedDisplayBacklight,
|
||||||
NotificationMessageTypeLedDisplayLock,
|
NotificationMessageTypeLedDisplayBacklightEnforceOn,
|
||||||
NotificationMessageTypeLedDisplayUnlock,
|
NotificationMessageTypeLedDisplayBacklightEnforceAuto,
|
||||||
|
|
||||||
NotificationMessageTypeDoNotReset,
|
NotificationMessageTypeDoNotReset,
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ void notification_sound_off() {
|
|||||||
static void notification_display_timer(void* ctx) {
|
static void notification_display_timer(void* ctx) {
|
||||||
furi_assert(ctx);
|
furi_assert(ctx);
|
||||||
NotificationApp* app = ctx;
|
NotificationApp* app = ctx;
|
||||||
notification_message(app, &sequence_display_off);
|
notification_message(app, &sequence_display_backlight_off);
|
||||||
}
|
}
|
||||||
|
|
||||||
// message processing
|
// message processing
|
||||||
@@ -174,7 +174,7 @@ void notification_process_notification_message(
|
|||||||
|
|
||||||
while(notification_message != NULL) {
|
while(notification_message != NULL) {
|
||||||
switch(notification_message->type) {
|
switch(notification_message->type) {
|
||||||
case NotificationMessageTypeLedDisplay:
|
case NotificationMessageTypeLedDisplayBacklight:
|
||||||
// if on - switch on and start timer
|
// if on - switch on and start timer
|
||||||
// if off - switch off and stop timer
|
// if off - switch off and stop timer
|
||||||
// on timer - switch off
|
// on timer - switch off
|
||||||
@@ -190,7 +190,7 @@ void notification_process_notification_message(
|
|||||||
}
|
}
|
||||||
reset_mask |= reset_display_mask;
|
reset_mask |= reset_display_mask;
|
||||||
break;
|
break;
|
||||||
case NotificationMessageTypeLedDisplayLock:
|
case NotificationMessageTypeLedDisplayBacklightEnforceOn:
|
||||||
furi_assert(app->display_led_lock < UINT8_MAX);
|
furi_assert(app->display_led_lock < UINT8_MAX);
|
||||||
app->display_led_lock++;
|
app->display_led_lock++;
|
||||||
if(app->display_led_lock == 1) {
|
if(app->display_led_lock == 1) {
|
||||||
@@ -199,7 +199,7 @@ void notification_process_notification_message(
|
|||||||
notification_message->data.led.value * display_brightness_setting);
|
notification_message->data.led.value * display_brightness_setting);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NotificationMessageTypeLedDisplayUnlock:
|
case NotificationMessageTypeLedDisplayBacklightEnforceAuto:
|
||||||
furi_assert(app->display_led_lock > 0);
|
furi_assert(app->display_led_lock > 0);
|
||||||
app->display_led_lock--;
|
app->display_led_lock--;
|
||||||
if(app->display_led_lock == 0) {
|
if(app->display_led_lock == 0) {
|
||||||
@@ -322,7 +322,7 @@ void notification_process_internal_message(NotificationApp* app, NotificationApp
|
|||||||
|
|
||||||
while(notification_message != NULL) {
|
while(notification_message != NULL) {
|
||||||
switch(notification_message->type) {
|
switch(notification_message->type) {
|
||||||
case NotificationMessageTypeLedDisplay:
|
case NotificationMessageTypeLedDisplayBacklight:
|
||||||
notification_apply_internal_led_layer(
|
notification_apply_internal_led_layer(
|
||||||
&app->display,
|
&app->display,
|
||||||
notification_settings_get_display_brightness(
|
notification_settings_get_display_brightness(
|
||||||
@@ -442,7 +442,7 @@ static void input_event_callback(const void* value, void* context) {
|
|||||||
furi_assert(value);
|
furi_assert(value);
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
NotificationApp* app = context;
|
NotificationApp* app = context;
|
||||||
notification_message(app, &sequence_display_on);
|
notification_message(app, &sequence_display_backlight_on);
|
||||||
}
|
}
|
||||||
|
|
||||||
// App alloc
|
// App alloc
|
||||||
@@ -482,7 +482,7 @@ static NotificationApp* notification_app_alloc() {
|
|||||||
// display backlight control
|
// display backlight control
|
||||||
app->event_record = furi_record_open("input_events");
|
app->event_record = furi_record_open("input_events");
|
||||||
furi_pubsub_subscribe(app->event_record, input_event_callback, app);
|
furi_pubsub_subscribe(app->event_record, input_event_callback, app);
|
||||||
notification_message(app, &sequence_display_on);
|
notification_message(app, &sequence_display_backlight_on);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,24 +4,27 @@
|
|||||||
|
|
||||||
/*********************************** Messages **********************************/
|
/*********************************** Messages **********************************/
|
||||||
|
|
||||||
// Display
|
/** Display: backlight wakeup */
|
||||||
const NotificationMessage message_display_on = {
|
const NotificationMessage message_display_backlight_on = {
|
||||||
.type = NotificationMessageTypeLedDisplay,
|
.type = NotificationMessageTypeLedDisplayBacklight,
|
||||||
.data.led.value = 0xFF,
|
.data.led.value = 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
const NotificationMessage message_display_off = {
|
/** Display: backlight force off */
|
||||||
.type = NotificationMessageTypeLedDisplay,
|
const NotificationMessage message_display_backlight_off = {
|
||||||
|
.type = NotificationMessageTypeLedDisplayBacklight,
|
||||||
.data.led.value = 0x00,
|
.data.led.value = 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
const NotificationMessage message_display_lock = {
|
/** Display: backlight always on */
|
||||||
.type = NotificationMessageTypeLedDisplayLock,
|
const NotificationMessage message_display_backlight_enforce_on = {
|
||||||
|
.type = NotificationMessageTypeLedDisplayBacklightEnforceOn,
|
||||||
.data.led.value = 0xFF,
|
.data.led.value = 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
const NotificationMessage message_display_unlock = {
|
/** Display: automatic backlight management, with configured timeout */
|
||||||
.type = NotificationMessageTypeLedDisplayUnlock,
|
const NotificationMessage message_display_backlight_enforce_auto = {
|
||||||
|
.type = NotificationMessageTypeLedDisplayBacklightEnforceAuto,
|
||||||
.data.led.value = 0x00,
|
.data.led.value = 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -166,7 +169,7 @@ const NotificationSequence sequence_reset_rgb = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const NotificationSequence sequence_reset_display = {
|
const NotificationSequence sequence_reset_display = {
|
||||||
&message_display_off,
|
&message_display_backlight_off,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -188,29 +191,31 @@ const NotificationSequence sequence_set_vibro_on = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
const NotificationSequence sequence_display_on = {
|
const NotificationSequence sequence_display_backlight_on = {
|
||||||
&message_display_on,
|
&message_display_backlight_on,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
const NotificationSequence sequence_display_off = {
|
const NotificationSequence sequence_display_backlight_off = {
|
||||||
&message_display_off,
|
&message_display_backlight_off,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
const NotificationSequence sequence_display_lock = {
|
/** Display: backlight always on lock */
|
||||||
&message_display_lock,
|
const NotificationSequence sequence_display_backlight_enforce_on = {
|
||||||
|
&message_display_backlight_enforce_on,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
const NotificationSequence sequence_display_unlock = {
|
/** Display: backlight always on unlock */
|
||||||
&message_display_unlock,
|
const NotificationSequence sequence_display_backlight_enforce_auto = {
|
||||||
|
&message_display_backlight_enforce_auto,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
const NotificationSequence sequence_display_off_delay_1000 = {
|
const NotificationSequence sequence_display_backlight_off_delay_1000 = {
|
||||||
&message_delay_1000,
|
&message_delay_1000,
|
||||||
&message_display_off,
|
&message_display_backlight_off,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -383,7 +388,7 @@ const NotificationSequence sequence_double_vibro = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const NotificationSequence sequence_success = {
|
const NotificationSequence sequence_success = {
|
||||||
&message_display_on,
|
&message_display_backlight_on,
|
||||||
&message_green_255,
|
&message_green_255,
|
||||||
&message_vibro_on,
|
&message_vibro_on,
|
||||||
&message_note_c5,
|
&message_note_c5,
|
||||||
@@ -400,7 +405,7 @@ const NotificationSequence sequence_success = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const NotificationSequence sequence_error = {
|
const NotificationSequence sequence_error = {
|
||||||
&message_display_on,
|
&message_display_backlight_on,
|
||||||
&message_red_255,
|
&message_red_255,
|
||||||
&message_vibro_on,
|
&message_vibro_on,
|
||||||
&message_note_c5,
|
&message_note_c5,
|
||||||
@@ -422,27 +427,27 @@ const NotificationSequence sequence_audiovisual_alert = {
|
|||||||
&message_force_display_brightness_setting_1f,
|
&message_force_display_brightness_setting_1f,
|
||||||
&message_vibro_on,
|
&message_vibro_on,
|
||||||
|
|
||||||
&message_display_on,
|
&message_display_backlight_on,
|
||||||
&message_note_c7,
|
&message_note_c7,
|
||||||
&message_delay_250,
|
&message_delay_250,
|
||||||
|
|
||||||
&message_display_off,
|
&message_display_backlight_off,
|
||||||
&message_note_c4,
|
&message_note_c4,
|
||||||
&message_delay_250,
|
&message_delay_250,
|
||||||
|
|
||||||
&message_display_on,
|
&message_display_backlight_on,
|
||||||
&message_note_c7,
|
&message_note_c7,
|
||||||
&message_delay_250,
|
&message_delay_250,
|
||||||
|
|
||||||
&message_display_off,
|
&message_display_backlight_off,
|
||||||
&message_note_c4,
|
&message_note_c4,
|
||||||
&message_delay_250,
|
&message_delay_250,
|
||||||
|
|
||||||
&message_display_on,
|
&message_display_backlight_on,
|
||||||
&message_note_c7,
|
&message_note_c7,
|
||||||
&message_delay_250,
|
&message_delay_250,
|
||||||
|
|
||||||
&message_display_off,
|
&message_display_backlight_off,
|
||||||
&message_note_c4,
|
&message_note_c4,
|
||||||
&message_delay_250,
|
&message_delay_250,
|
||||||
|
|
||||||
|
|||||||
@@ -9,15 +9,10 @@ extern "C" {
|
|||||||
/*********************************** Messages **********************************/
|
/*********************************** Messages **********************************/
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
|
extern const NotificationMessage message_display_backlight_on;
|
||||||
/** Display: backlight wakeup */
|
extern const NotificationMessage message_display_backlight_off;
|
||||||
extern const NotificationMessage message_display_on;
|
extern const NotificationMessage message_display_backlight_enforce_on;
|
||||||
/** Display: backlight force off */
|
extern const NotificationMessage message_display_backlight_enforce_auto;
|
||||||
extern const NotificationMessage message_display_off;
|
|
||||||
/** Display: backlight always on lock */
|
|
||||||
extern const NotificationMessage message_display_lock;
|
|
||||||
/** Display: backlight always on unlock */
|
|
||||||
extern const NotificationMessage message_display_unlock;
|
|
||||||
|
|
||||||
// Led ON
|
// Led ON
|
||||||
extern const NotificationMessage message_red_255;
|
extern const NotificationMessage message_red_255;
|
||||||
@@ -71,15 +66,16 @@ extern const NotificationSequence sequence_set_vibro_on;
|
|||||||
|
|
||||||
// Display
|
// Display
|
||||||
/** Display: backlight wakeup */
|
/** Display: backlight wakeup */
|
||||||
extern const NotificationSequence sequence_display_on;
|
extern const NotificationSequence sequence_display_backlight_on;
|
||||||
/** Display: backlight force off */
|
/** Display: backlight force off */
|
||||||
extern const NotificationSequence sequence_display_off;
|
extern const NotificationSequence sequence_display_backlight_off;
|
||||||
/** Display: backlight always on lock */
|
|
||||||
extern const NotificationSequence sequence_display_lock;
|
|
||||||
/** Display: backlight always on unlock */
|
|
||||||
extern const NotificationSequence sequence_display_unlock;
|
|
||||||
/** Display: backlight force off after a delay of 1000ms */
|
/** Display: backlight force off after a delay of 1000ms */
|
||||||
extern const NotificationSequence sequence_display_off_delay_1000;
|
extern const NotificationSequence sequence_display_backlight_off_delay_1000;
|
||||||
|
|
||||||
|
/** Display: backlight always on lock */
|
||||||
|
extern const NotificationSequence sequence_display_backlight_enforce_on;
|
||||||
|
/** Display: backlight always on unlock */
|
||||||
|
extern const NotificationSequence sequence_display_backlight_enforce_auto;
|
||||||
|
|
||||||
// Charging
|
// Charging
|
||||||
extern const NotificationSequence sequence_charging;
|
extern const NotificationSequence sequence_charging;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ static void backlight_changed(VariableItem* item) {
|
|||||||
|
|
||||||
variable_item_set_current_value_text(item, backlight_text[index]);
|
variable_item_set_current_value_text(item, backlight_text[index]);
|
||||||
app->notification->settings.display_brightness = backlight_value[index];
|
app->notification->settings.display_brightness = backlight_value[index];
|
||||||
notification_message(app->notification, &sequence_display_on);
|
notification_message(app->notification, &sequence_display_backlight_on);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void screen_changed(VariableItem* item) {
|
static void screen_changed(VariableItem* item) {
|
||||||
@@ -79,7 +79,7 @@ static void screen_changed(VariableItem* item) {
|
|||||||
|
|
||||||
variable_item_set_current_value_text(item, delay_text[index]);
|
variable_item_set_current_value_text(item, delay_text[index]);
|
||||||
app->notification->settings.display_off_delay_ms = delay_value[index];
|
app->notification->settings.display_off_delay_ms = delay_value[index];
|
||||||
notification_message(app->notification, &sequence_display_on);
|
notification_message(app->notification, &sequence_display_backlight_on);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NotificationMessage apply_message = {
|
const NotificationMessage apply_message = {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ static void battery_test_battery_info_update_model(void* context) {
|
|||||||
.health = app->info.health,
|
.health = app->info.health,
|
||||||
};
|
};
|
||||||
battery_info_set_data(app->batery_info, &battery_info_data);
|
battery_info_set_data(app->batery_info, &battery_info_data);
|
||||||
notification_message(app->notifications, &sequence_display_on);
|
notification_message(app->notifications, &sequence_display_backlight_on);
|
||||||
}
|
}
|
||||||
|
|
||||||
BatteryTestApp* battery_test_alloc() {
|
BatteryTestApp* battery_test_alloc() {
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ void rpc_cli_command_start_session(Cli* cli, string_t args, void* context) {
|
|||||||
size_t size_received = 0;
|
size_t size_received = 0;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
size_received = furi_hal_vcp_rx_with_timeout(buffer, CLI_READ_BUFFER_SIZE, 50);
|
size_received = cli_read_timeout(cli_rpc.cli, buffer, CLI_READ_BUFFER_SIZE, 50);
|
||||||
if(!furi_hal_vcp_is_connected() || cli_rpc.session_close_request) {
|
if(!cli_is_connected(cli_rpc.cli) || cli_rpc.session_close_request) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,12 +39,10 @@ void storage_data_init(StorageData* storage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool storage_data_lock(StorageData* storage) {
|
bool storage_data_lock(StorageData* storage) {
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
return (osMutexAcquire(storage->mutex, osWaitForever) == osOK);
|
return (osMutexAcquire(storage->mutex, osWaitForever) == osOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool storage_data_unlock(StorageData* storage) {
|
bool storage_data_unlock(StorageData* storage) {
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
return (osMutexRelease(storage->mutex) == osOK);
|
return (osMutexRelease(storage->mutex) == osOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ struct SubGhzChatWorker {
|
|||||||
volatile bool worker_stoping;
|
volatile bool worker_stoping;
|
||||||
osMessageQueueId_t event_queue;
|
osMessageQueueId_t event_queue;
|
||||||
uint32_t last_time_rx_data;
|
uint32_t last_time_rx_data;
|
||||||
|
|
||||||
|
Cli* cli;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Worker thread
|
/** Worker thread
|
||||||
@@ -27,7 +29,7 @@ static int32_t subghz_chat_worker_thread(void* context) {
|
|||||||
event.event = SubGhzChatEventUserEntrance;
|
event.event = SubGhzChatEventUserEntrance;
|
||||||
osMessageQueuePut(instance->event_queue, &event, 0, 0);
|
osMessageQueuePut(instance->event_queue, &event, 0, 0);
|
||||||
while(instance->worker_running) {
|
while(instance->worker_running) {
|
||||||
if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 1000) == 1) {
|
if(cli_read_timeout(instance->cli, (uint8_t*)&c, 1, 1000) == 1) {
|
||||||
event.event = SubGhzChatEventInputData;
|
event.event = SubGhzChatEventInputData;
|
||||||
event.c = c;
|
event.c = c;
|
||||||
osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever);
|
osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever);
|
||||||
@@ -52,9 +54,11 @@ static void subghz_chat_worker_update_rx_event_chat(void* context) {
|
|||||||
osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever);
|
osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever);
|
||||||
}
|
}
|
||||||
|
|
||||||
SubGhzChatWorker* subghz_chat_worker_alloc() {
|
SubGhzChatWorker* subghz_chat_worker_alloc(Cli* cli) {
|
||||||
SubGhzChatWorker* instance = malloc(sizeof(SubGhzChatWorker));
|
SubGhzChatWorker* instance = malloc(sizeof(SubGhzChatWorker));
|
||||||
|
|
||||||
|
instance->cli = cli;
|
||||||
|
|
||||||
instance->thread = furi_thread_alloc();
|
instance->thread = furi_thread_alloc();
|
||||||
furi_thread_set_name(instance->thread, "SubGhzChat");
|
furi_thread_set_name(instance->thread, "SubGhzChat");
|
||||||
furi_thread_set_stack_size(instance->thread, 2048);
|
furi_thread_set_stack_size(instance->thread, 2048);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../subghz_i.h"
|
#include "../subghz_i.h"
|
||||||
|
#include <cli/cli.h>
|
||||||
|
|
||||||
typedef struct SubGhzChatWorker SubGhzChatWorker;
|
typedef struct SubGhzChatWorker SubGhzChatWorker;
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ typedef struct {
|
|||||||
char c;
|
char c;
|
||||||
} SubGhzChatEvent;
|
} SubGhzChatEvent;
|
||||||
|
|
||||||
SubGhzChatWorker* subghz_chat_worker_alloc();
|
SubGhzChatWorker* subghz_chat_worker_alloc(Cli* cli);
|
||||||
void subghz_chat_worker_free(SubGhzChatWorker* instance);
|
void subghz_chat_worker_free(SubGhzChatWorker* instance);
|
||||||
bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency);
|
bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency);
|
||||||
void subghz_chat_worker_stop(SubGhzChatWorker* instance);
|
void subghz_chat_worker_stop(SubGhzChatWorker* instance);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
#include <flipper_format/flipper_format_i.h>
|
#include <flipper_format/flipper_format_i.h>
|
||||||
#include <lib/toolbox/stream/stream.h>
|
#include <lib/toolbox/stream/stream.h>
|
||||||
|
#include <lib/subghz/protocols/registry.h>
|
||||||
|
|
||||||
#define TAG "SubGhzSetType"
|
#define TAG "SubGhzSetType"
|
||||||
|
|
||||||
@@ -21,13 +22,16 @@ enum SubmenuIndex {
|
|||||||
SubmenuIndexGateTX,
|
SubmenuIndexGateTX,
|
||||||
SubmenuIndexDoorHan_315_00,
|
SubmenuIndexDoorHan_315_00,
|
||||||
SubmenuIndexDoorHan_433_92,
|
SubmenuIndexDoorHan_433_92,
|
||||||
|
SubmenuIndexFirefly_300_00,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool subghz_scene_set_type_submenu_gen_data_protocol(
|
bool subghz_scene_set_type_submenu_gen_data_protocol(
|
||||||
void* context,
|
void* context,
|
||||||
const char* protocol_name,
|
const char* protocol_name,
|
||||||
uint64_t key,
|
uint64_t key,
|
||||||
uint32_t bit) {
|
uint32_t bit,
|
||||||
|
uint32_t frequency,
|
||||||
|
FuriHalSubGhzPreset preset) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
|
|
||||||
@@ -46,10 +50,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol(
|
|||||||
Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data);
|
Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data);
|
||||||
stream_clean(fff_data_stream);
|
stream_clean(fff_data_stream);
|
||||||
if(!subghz_protocol_decoder_base_serialize(
|
if(!subghz_protocol_decoder_base_serialize(
|
||||||
subghz->txrx->decoder_result,
|
subghz->txrx->decoder_result, subghz->txrx->fff_data, frequency, preset)) {
|
||||||
subghz->txrx->fff_data,
|
|
||||||
subghz_setting_get_default_frequency(subghz->setting),
|
|
||||||
FuriHalSubGhzPresetOok650Async)) {
|
|
||||||
FURI_LOG_E(TAG, "Unable to serialize");
|
FURI_LOG_E(TAG, "Unable to serialize");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -115,6 +116,12 @@ void subghz_scene_set_type_on_enter(void* context) {
|
|||||||
SubmenuIndexCAME24bit,
|
SubmenuIndexCAME24bit,
|
||||||
subghz_scene_set_type_submenu_callback,
|
subghz_scene_set_type_submenu_callback,
|
||||||
subghz);
|
subghz);
|
||||||
|
submenu_add_item(
|
||||||
|
subghz->submenu,
|
||||||
|
"Firefly_300",
|
||||||
|
SubmenuIndexFirefly_300_00,
|
||||||
|
subghz_scene_set_type_submenu_callback,
|
||||||
|
subghz);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
subghz->submenu,
|
subghz->submenu,
|
||||||
"CAME TWEE",
|
"CAME TWEE",
|
||||||
@@ -163,7 +170,13 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
|||||||
break;
|
break;
|
||||||
case SubmenuIndexPricenton:
|
case SubmenuIndexPricenton:
|
||||||
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
|
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
|
||||||
if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "Princeton", key, 24)) {
|
if(subghz_scene_set_type_submenu_gen_data_protocol(
|
||||||
|
subghz,
|
||||||
|
SUBGHZ_PROTOCOL_PRINCETON_NAME,
|
||||||
|
key,
|
||||||
|
24,
|
||||||
|
433920000,
|
||||||
|
FuriHalSubGhzPresetOok650Async)) {
|
||||||
uint32_t te = 400;
|
uint32_t te = 400;
|
||||||
flipper_format_update_uint32(subghz->txrx->fff_data, "TE", (uint32_t*)&te, 1);
|
flipper_format_update_uint32(subghz->txrx->fff_data, "TE", (uint32_t*)&te, 1);
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
@@ -171,32 +184,74 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
|||||||
break;
|
break;
|
||||||
case SubmenuIndexNiceFlo12bit:
|
case SubmenuIndexNiceFlo12bit:
|
||||||
key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
|
key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
|
||||||
if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "Nice FLO", key, 12)) {
|
if(subghz_scene_set_type_submenu_gen_data_protocol(
|
||||||
|
subghz,
|
||||||
|
SUBGHZ_PROTOCOL_NICE_FLO_NAME,
|
||||||
|
key,
|
||||||
|
12,
|
||||||
|
433920000,
|
||||||
|
FuriHalSubGhzPresetOok650Async)) {
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexNiceFlo24bit:
|
case SubmenuIndexNiceFlo24bit:
|
||||||
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
|
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
|
||||||
if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "Nice FLO", key, 24)) {
|
if(subghz_scene_set_type_submenu_gen_data_protocol(
|
||||||
|
subghz,
|
||||||
|
SUBGHZ_PROTOCOL_NICE_FLO_NAME,
|
||||||
|
key,
|
||||||
|
24,
|
||||||
|
433920000,
|
||||||
|
FuriHalSubGhzPresetOok650Async)) {
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexCAME12bit:
|
case SubmenuIndexCAME12bit:
|
||||||
key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
|
key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
|
||||||
if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "CAME", key, 12)) {
|
if(subghz_scene_set_type_submenu_gen_data_protocol(
|
||||||
|
subghz,
|
||||||
|
SUBGHZ_PROTOCOL_CAME_NAME,
|
||||||
|
key,
|
||||||
|
12,
|
||||||
|
433920000,
|
||||||
|
FuriHalSubGhzPresetOok650Async)) {
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexCAME24bit:
|
case SubmenuIndexCAME24bit:
|
||||||
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
|
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
|
||||||
if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "CAME", key, 24)) {
|
if(subghz_scene_set_type_submenu_gen_data_protocol(
|
||||||
|
subghz,
|
||||||
|
SUBGHZ_PROTOCOL_CAME_NAME,
|
||||||
|
key,
|
||||||
|
24,
|
||||||
|
433920000,
|
||||||
|
FuriHalSubGhzPresetOok650Async)) {
|
||||||
|
generated_protocol = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SubmenuIndexFirefly_300_00:
|
||||||
|
key = (key & 0x3FF);
|
||||||
|
if(subghz_scene_set_type_submenu_gen_data_protocol(
|
||||||
|
subghz,
|
||||||
|
SUBGHZ_PROTOCOL_FIREFLY_NAME,
|
||||||
|
key,
|
||||||
|
10,
|
||||||
|
300000000,
|
||||||
|
FuriHalSubGhzPresetOok650Async)) {
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexCAMETwee:
|
case SubmenuIndexCAMETwee:
|
||||||
key = (key & 0x0FFFFFF0);
|
key = (key & 0x0FFFFFF0);
|
||||||
key = 0x003FFF7200000000 | (key ^ 0xE0E0E0EE);
|
key = 0x003FFF7200000000 | (key ^ 0xE0E0E0EE);
|
||||||
if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "CAME TWEE", key, 54)) {
|
if(subghz_scene_set_type_submenu_gen_data_protocol(
|
||||||
|
subghz,
|
||||||
|
SUBGHZ_PROTOCOL_CAME_TWEE_NAME,
|
||||||
|
key,
|
||||||
|
54,
|
||||||
|
433920000,
|
||||||
|
FuriHalSubGhzPresetOok650Async)) {
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -209,13 +264,19 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
|||||||
case SubmenuIndexGateTX:
|
case SubmenuIndexGateTX:
|
||||||
key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?)
|
key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?)
|
||||||
uint64_t rev_key = subghz_protocol_blocks_reverse_key(key, 24);
|
uint64_t rev_key = subghz_protocol_blocks_reverse_key(key, 24);
|
||||||
if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "GateTX", rev_key, 24)) {
|
if(subghz_scene_set_type_submenu_gen_data_protocol(
|
||||||
|
subghz,
|
||||||
|
SUBGHZ_PROTOCOL_GATE_TX_NAME,
|
||||||
|
rev_key,
|
||||||
|
24,
|
||||||
|
433920000,
|
||||||
|
FuriHalSubGhzPresetOok650Async)) {
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexDoorHan_433_92:
|
case SubmenuIndexDoorHan_433_92:
|
||||||
subghz->txrx->transmitter =
|
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
||||||
subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq");
|
subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME);
|
||||||
if(subghz->txrx->transmitter) {
|
if(subghz->txrx->transmitter) {
|
||||||
subghz_protocol_keeloq_create_data(
|
subghz_protocol_keeloq_create_data(
|
||||||
subghz->txrx->transmitter->protocol_instance,
|
subghz->txrx->transmitter->protocol_instance,
|
||||||
@@ -238,8 +299,8 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexDoorHan_315_00:
|
case SubmenuIndexDoorHan_315_00:
|
||||||
subghz->txrx->transmitter =
|
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
||||||
subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq");
|
subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME);
|
||||||
if(subghz->txrx->transmitter) {
|
if(subghz->txrx->transmitter) {
|
||||||
subghz_protocol_keeloq_create_data(
|
subghz_protocol_keeloq_create_data(
|
||||||
subghz->txrx->transmitter->protocol_instance,
|
subghz->txrx->transmitter->protocol_instance,
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SubGhzChatWorker* subghz_chat = subghz_chat_worker_alloc();
|
SubGhzChatWorker* subghz_chat = subghz_chat_worker_alloc(cli);
|
||||||
if(!subghz_chat_worker_start(subghz_chat, frequency)) {
|
if(!subghz_chat_worker_start(subghz_chat, frequency)) {
|
||||||
printf("Startup error SubGhzChatWorker\r\n");
|
printf("Startup error SubGhzChatWorker\r\n");
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ bool u2f_scene_main_on_event(void* context, SceneManagerEvent event) {
|
|||||||
u2f_view_set_state(app->u2f_view, U2fMsgRegister);
|
u2f_view_set_state(app->u2f_view, U2fMsgRegister);
|
||||||
else if(event.event == U2fCustomEventAuth)
|
else if(event.event == U2fCustomEventAuth)
|
||||||
u2f_view_set_state(app->u2f_view, U2fMsgAuth);
|
u2f_view_set_state(app->u2f_view, U2fMsgAuth);
|
||||||
notification_message(app->notifications, &sequence_display_on);
|
notification_message(app->notifications, &sequence_display_backlight_on);
|
||||||
notification_message(app->notifications, &sequence_single_vibro);
|
notification_message(app->notifications, &sequence_single_vibro);
|
||||||
}
|
}
|
||||||
notification_message(app->notifications, &sequence_blink_magenta_10);
|
notification_message(app->notifications, &sequence_blink_magenta_10);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ static void sd_mount_callback(const void* message, void* context) {
|
|||||||
|
|
||||||
void updater_scene_main_on_enter(void* context) {
|
void updater_scene_main_on_enter(void* context) {
|
||||||
Updater* updater = (Updater*)context;
|
Updater* updater = (Updater*)context;
|
||||||
|
notification_message(updater->notification, &sequence_display_backlight_enforce_on);
|
||||||
UpdaterMainView* main_view = updater->main_view;
|
UpdaterMainView* main_view = updater->main_view;
|
||||||
|
|
||||||
FuriPubSubSubscription* sub =
|
FuriPubSubSubscription* sub =
|
||||||
@@ -92,8 +93,9 @@ bool updater_scene_main_on_event(void* context, SceneManagerEvent event) {
|
|||||||
void updater_scene_main_on_exit(void* context) {
|
void updater_scene_main_on_exit(void* context) {
|
||||||
Updater* updater = (Updater*)context;
|
Updater* updater = (Updater*)context;
|
||||||
|
|
||||||
|
notification_message(updater->notification, &sequence_display_backlight_enforce_auto);
|
||||||
furi_pubsub_unsubscribe(
|
furi_pubsub_unsubscribe(
|
||||||
storage_get_pubsub(updater->storage), updater_main_get_storage_pubsub(updater->main_view));
|
storage_get_pubsub(updater->storage), updater_main_get_storage_pubsub(updater->main_view));
|
||||||
|
|
||||||
scene_manager_set_scene_state(updater->scene_manager, UpdaterSceneMain, 0);
|
scene_manager_set_scene_state(updater->scene_manager, UpdaterSceneMain, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ Updater* updater_alloc(const char* arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updater->storage = furi_record_open("storage");
|
updater->storage = furi_record_open("storage");
|
||||||
|
updater->notification = furi_record_open("notification");
|
||||||
|
|
||||||
updater->gui = furi_record_open("gui");
|
updater->gui = furi_record_open("gui");
|
||||||
updater->view_dispatcher = view_dispatcher_alloc();
|
updater->view_dispatcher = view_dispatcher_alloc();
|
||||||
@@ -119,6 +120,7 @@ void updater_free(Updater* updater) {
|
|||||||
|
|
||||||
furi_record_close("gui");
|
furi_record_close("gui");
|
||||||
furi_record_close("storage");
|
furi_record_close("storage");
|
||||||
|
furi_record_close("notification");
|
||||||
|
|
||||||
free(updater);
|
free(updater);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <gui/scene_manager.h>
|
#include <gui/scene_manager.h>
|
||||||
#include <gui/modules/widget.h>
|
#include <gui/modules/widget.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
#include <notification/notification_app.h>
|
||||||
#include <update_util/update_operation.h>
|
#include <update_util/update_operation.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -41,6 +42,7 @@ typedef struct UpdaterManifestProcessingState {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
// GUI
|
// GUI
|
||||||
Gui* gui;
|
Gui* gui;
|
||||||
|
NotificationApp* notification;
|
||||||
SceneManager* scene_manager;
|
SceneManager* scene_manager;
|
||||||
ViewDispatcher* view_dispatcher;
|
ViewDispatcher* view_dispatcher;
|
||||||
Storage* storage;
|
Storage* storage;
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ typedef enum {
|
|||||||
* keep debugger enabled while in any low power mode when set to 1
|
* keep debugger enabled while in any low power mode when set to 1
|
||||||
* should be set to 0 in production
|
* should be set to 0 in production
|
||||||
*/
|
*/
|
||||||
#define CFG_DEBUGGER_SUPPORTED 0
|
#define CFG_DEBUGGER_SUPPORTED 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When set to 1, the traces are enabled in the BLE services
|
* When set to 1, the traces are enabled in the BLE services
|
||||||
|
|||||||
@@ -1,25 +1,3 @@
|
|||||||
/* USER CODE BEGIN Header */
|
|
||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* File Name : app_debug.c
|
|
||||||
* Description : Debug capabilities source file for STM32WPAN Middleware
|
|
||||||
******************************************************************************
|
|
||||||
* @attention
|
|
||||||
*
|
|
||||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
|
||||||
* All rights reserved.</center></h2>
|
|
||||||
*
|
|
||||||
* This software component is licensed by ST under Ultimate Liberty license
|
|
||||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at:
|
|
||||||
* www.st.com/SLA0044
|
|
||||||
*
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
/* USER CODE END Header */
|
|
||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
|
||||||
/* USER CODE BEGIN Includes */
|
|
||||||
#include "utilities_common.h"
|
#include "utilities_common.h"
|
||||||
|
|
||||||
#include "app_common.h"
|
#include "app_common.h"
|
||||||
@@ -28,10 +6,7 @@
|
|||||||
#include "tl.h"
|
#include "tl.h"
|
||||||
#include "dbg_trace.h"
|
#include "dbg_trace.h"
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
/* USER CODE END Includes */
|
|
||||||
|
|
||||||
/* Private typedef -----------------------------------------------------------*/
|
|
||||||
/* USER CODE BEGIN PTD */
|
|
||||||
typedef PACKED_STRUCT {
|
typedef PACKED_STRUCT {
|
||||||
GPIO_TypeDef* port;
|
GPIO_TypeDef* port;
|
||||||
uint16_t pin;
|
uint16_t pin;
|
||||||
@@ -39,10 +14,7 @@ typedef PACKED_STRUCT {
|
|||||||
uint8_t reserved;
|
uint8_t reserved;
|
||||||
}
|
}
|
||||||
APPD_GpioConfig_t;
|
APPD_GpioConfig_t;
|
||||||
/* USER CODE END PTD */
|
|
||||||
|
|
||||||
/* Private defines -----------------------------------------------------------*/
|
|
||||||
/* USER CODE BEGIN PD */
|
|
||||||
#define GPIO_NBR_OF_RF_SIGNALS 9
|
#define GPIO_NBR_OF_RF_SIGNALS 9
|
||||||
#define GPIO_CFG_NBR_OF_FEATURES 34
|
#define GPIO_CFG_NBR_OF_FEATURES 34
|
||||||
#define NBR_OF_TRACES_CONFIG_PARAMETERS 4
|
#define NBR_OF_TRACES_CONFIG_PARAMETERS 4
|
||||||
@@ -51,12 +23,11 @@ APPD_GpioConfig_t;
|
|||||||
/**
|
/**
|
||||||
* THIS SHALL BE SET TO A VALUE DIFFERENT FROM 0 ONLY ON REQUEST FROM ST SUPPORT
|
* THIS SHALL BE SET TO A VALUE DIFFERENT FROM 0 ONLY ON REQUEST FROM ST SUPPORT
|
||||||
*/
|
*/
|
||||||
#define BLE_DTB_CFG 7
|
#define BLE_DTB_CFG 0
|
||||||
|
// #define BLE_DTB_CFG 7
|
||||||
#define SYS_DBG_CFG1 (SHCI_C2_DEBUG_OPTIONS_IPCORE_LP | SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN)
|
#define SYS_DBG_CFG1 (SHCI_C2_DEBUG_OPTIONS_IPCORE_LP | SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN)
|
||||||
/* USER CODE END PD */
|
|
||||||
|
|
||||||
/* Private variables ---------------------------------------------------------*/
|
/* Private variables ---------------------------------------------------------*/
|
||||||
/* USER CODE BEGIN PV */
|
|
||||||
PLACE_IN_SECTION("MB_MEM2")
|
PLACE_IN_SECTION("MB_MEM2")
|
||||||
ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig = {0, 0, 0, 0};
|
ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig = {0, 0, 0, 0};
|
||||||
PLACE_IN_SECTION("MB_MEM2")
|
PLACE_IN_SECTION("MB_MEM2")
|
||||||
@@ -91,7 +62,7 @@ static const APPD_GpioConfig_t aGpioConfigList[GPIO_CFG_NBR_OF_FEATURES] = {
|
|||||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_TRACES_TX - Set on Entry / Reset on Exit */
|
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_TRACES_TX - Set on Entry / Reset on Exit */
|
||||||
{GPIOA, LL_GPIO_PIN_6, 1, 0}, /* HARD_FAULT - Set on Entry / Reset on Exit */
|
{GPIOA, LL_GPIO_PIN_6, 1, 0}, /* HARD_FAULT - Set on Entry / Reset on Exit */
|
||||||
/* From v1.1.1 */
|
/* From v1.1.1 */
|
||||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */
|
{GPIOC, LL_GPIO_PIN_1, 1, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */
|
||||||
/* From v1.2.0 */
|
/* From v1.2.0 */
|
||||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */
|
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */
|
||||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */
|
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */
|
||||||
@@ -130,65 +101,20 @@ static const APPD_GpioConfig_t aRfConfigList[GPIO_NBR_OF_RF_SIGNALS] = {
|
|||||||
{GPIOB, LL_GPIO_PIN_10, 0, 0}, /* DTB18 - FSM4 */
|
{GPIOB, LL_GPIO_PIN_10, 0, 0}, /* DTB18 - FSM4 */
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
/* USER CODE END PV */
|
|
||||||
|
|
||||||
/* Global variables ----------------------------------------------------------*/
|
|
||||||
/* USER CODE BEGIN GV */
|
|
||||||
/* USER CODE END GV */
|
|
||||||
|
|
||||||
/* Private function prototypes -----------------------------------------------*/
|
|
||||||
/* USER CODE BEGIN PFP */
|
|
||||||
static void APPD_SetCPU2GpioConfig(void);
|
static void APPD_SetCPU2GpioConfig(void);
|
||||||
static void APPD_BleDtbCfg(void);
|
static void APPD_BleDtbCfg(void);
|
||||||
/* USER CODE END PFP */
|
|
||||||
|
|
||||||
/* Functions Definition ------------------------------------------------------*/
|
|
||||||
void APPD_Init(void) {
|
|
||||||
/* USER CODE BEGIN APPD_Init */
|
|
||||||
#if(CFG_DEBUGGER_SUPPORTED == 1)
|
|
||||||
/**
|
|
||||||
* Keep debugger enabled while in any low power mode
|
|
||||||
*/
|
|
||||||
LL_DBGMCU_EnableDBGSleepMode();
|
|
||||||
LL_DBGMCU_EnableDBGStopMode();
|
|
||||||
|
|
||||||
/***************** ENABLE DEBUGGER *************************************/
|
|
||||||
LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48);
|
|
||||||
|
|
||||||
#else
|
|
||||||
LL_GPIO_InitTypeDef gpio_config = {0};
|
|
||||||
LL_PWR_EnableVddUSB();
|
|
||||||
|
|
||||||
gpio_config.Mode = LL_GPIO_MODE_ANALOG;
|
|
||||||
gpio_config.Speed = LL_GPIO_SPEED_FREQ_LOW;
|
|
||||||
// gpio_config.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
|
||||||
// gpio_config.Pull = LL_GPIO_PULL_NO;
|
|
||||||
// gpio_config.Alternate = LL_GPIO_AF_10;
|
|
||||||
gpio_config.Pin = LL_GPIO_PIN_15 | LL_GPIO_PIN_14 | LL_GPIO_PIN_13;
|
|
||||||
LL_GPIO_Init(GPIOA, &gpio_config);
|
|
||||||
|
|
||||||
gpio_config.Pin = LL_GPIO_PIN_4 | LL_GPIO_PIN_3;
|
|
||||||
LL_GPIO_Init(GPIOB, &gpio_config);
|
|
||||||
|
|
||||||
LL_DBGMCU_DisableDBGSleepMode();
|
|
||||||
LL_DBGMCU_DisableDBGStopMode();
|
|
||||||
LL_DBGMCU_DisableDBGStandbyMode();
|
|
||||||
|
|
||||||
#endif /* (CFG_DEBUGGER_SUPPORTED == 1) */
|
|
||||||
|
|
||||||
|
void APPD_Init() {
|
||||||
#if(CFG_DEBUG_TRACE != 0)
|
#if(CFG_DEBUG_TRACE != 0)
|
||||||
DbgTraceInit();
|
DbgTraceInit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
APPD_SetCPU2GpioConfig();
|
APPD_SetCPU2GpioConfig();
|
||||||
APPD_BleDtbCfg();
|
APPD_BleDtbCfg();
|
||||||
|
|
||||||
/* USER CODE END APPD_Init */
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void APPD_EnableCPU2(void) {
|
void APPD_EnableCPU2(void) {
|
||||||
/* USER CODE BEGIN APPD_EnableCPU2 */
|
|
||||||
SHCI_C2_DEBUG_Init_Cmd_Packet_t DebugCmdPacket = {
|
SHCI_C2_DEBUG_Init_Cmd_Packet_t DebugCmdPacket = {
|
||||||
{{0, 0, 0}}, /**< Does not need to be initialized */
|
{{0, 0, 0}}, /**< Does not need to be initialized */
|
||||||
{(uint8_t*)aGpioConfigList,
|
{(uint8_t*)aGpioConfigList,
|
||||||
@@ -204,6 +130,7 @@ void APPD_EnableCPU2(void) {
|
|||||||
/** GPIO DEBUG Initialization */
|
/** GPIO DEBUG Initialization */
|
||||||
SHCI_C2_DEBUG_Init(&DebugCmdPacket);
|
SHCI_C2_DEBUG_Init(&DebugCmdPacket);
|
||||||
|
|
||||||
|
// We don't need External Power Amplifier
|
||||||
// LL_GPIO_InitTypeDef gpio_config;
|
// LL_GPIO_InitTypeDef gpio_config;
|
||||||
// gpio_config.Pull = GPIO_NOPULL;
|
// gpio_config.Pull = GPIO_NOPULL;
|
||||||
// gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
|
// gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
@@ -212,17 +139,10 @@ void APPD_EnableCPU2(void) {
|
|||||||
// HAL_GPIO_Init(GPIOC, &gpio_config);
|
// HAL_GPIO_Init(GPIOC, &gpio_config);
|
||||||
// SHCI_C2_ExtpaConfig((uint32_t)GPIOC, LL_GPIO_PIN_3, EXT_PA_ENABLED_LOW, EXT_PA_ENABLED);
|
// SHCI_C2_ExtpaConfig((uint32_t)GPIOC, LL_GPIO_PIN_3, EXT_PA_ENABLED_LOW, EXT_PA_ENABLED);
|
||||||
|
|
||||||
/* USER CODE END APPD_EnableCPU2 */
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
*
|
|
||||||
* LOCAL FUNCTIONS
|
|
||||||
*
|
|
||||||
*************************************************************/
|
|
||||||
static void APPD_SetCPU2GpioConfig(void) {
|
static void APPD_SetCPU2GpioConfig(void) {
|
||||||
/* USER CODE BEGIN APPD_SetCPU2GpioConfig */
|
|
||||||
LL_GPIO_InitTypeDef gpio_config = {0};
|
LL_GPIO_InitTypeDef gpio_config = {0};
|
||||||
uint8_t local_loop;
|
uint8_t local_loop;
|
||||||
uint16_t gpioa_pin_list;
|
uint16_t gpioa_pin_list;
|
||||||
@@ -259,8 +179,9 @@ static void APPD_SetCPU2GpioConfig(void) {
|
|||||||
gpio_config.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
gpio_config.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
|
||||||
gpio_config.Pull = LL_GPIO_PULL_NO;
|
gpio_config.Pull = LL_GPIO_PULL_NO;
|
||||||
|
|
||||||
gpio_config.Pin = LL_GPIO_PIN_15 | LL_GPIO_PIN_14 | LL_GPIO_PIN_13;
|
// Never disable SWD, why would you?
|
||||||
LL_GPIO_Init(GPIOA, &gpio_config);
|
// gpio_config.Pin = LL_GPIO_PIN_15 | LL_GPIO_PIN_14 | LL_GPIO_PIN_13;
|
||||||
|
// LL_GPIO_Init(GPIOA, &gpio_config);
|
||||||
|
|
||||||
if(gpioa_pin_list != 0) {
|
if(gpioa_pin_list != 0) {
|
||||||
gpio_config.Pin = gpioa_pin_list;
|
gpio_config.Pin = gpioa_pin_list;
|
||||||
@@ -282,13 +203,9 @@ static void APPD_SetCPU2GpioConfig(void) {
|
|||||||
LL_GPIO_Init(GPIOC, &gpio_config);
|
LL_GPIO_Init(GPIOC, &gpio_config);
|
||||||
LL_GPIO_ResetOutputPin(GPIOC, gpioa_pin_list);
|
LL_GPIO_ResetOutputPin(GPIOC, gpioa_pin_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* USER CODE END APPD_SetCPU2GpioConfig */
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void APPD_BleDtbCfg(void) {
|
static void APPD_BleDtbCfg(void) {
|
||||||
/* USER CODE BEGIN APPD_BleDtbCfg */
|
|
||||||
#if(BLE_DTB_CFG != 0)
|
#if(BLE_DTB_CFG != 0)
|
||||||
LL_GPIO_InitTypeDef gpio_config = {0};
|
LL_GPIO_InitTypeDef gpio_config = {0};
|
||||||
uint8_t local_loop;
|
uint8_t local_loop;
|
||||||
@@ -304,11 +221,9 @@ static void APPD_BleDtbCfg(void) {
|
|||||||
case(uint32_t)GPIOA:
|
case(uint32_t)GPIOA:
|
||||||
gpioa_pin_list |= aRfConfigList[local_loop].pin;
|
gpioa_pin_list |= aRfConfigList[local_loop].pin;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case(uint32_t)GPIOB:
|
case(uint32_t)GPIOB:
|
||||||
gpiob_pin_list |= aRfConfigList[local_loop].pin;
|
gpiob_pin_list |= aRfConfigList[local_loop].pin;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -334,16 +249,8 @@ static void APPD_BleDtbCfg(void) {
|
|||||||
LL_GPIO_Init(GPIOB, &gpio_config);
|
LL_GPIO_Init(GPIOB, &gpio_config);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* USER CODE END APPD_BleDtbCfg */
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
*
|
|
||||||
* WRAP FUNCTIONS
|
|
||||||
*
|
|
||||||
*************************************************************/
|
|
||||||
#if(CFG_DEBUG_TRACE != 0)
|
#if(CFG_DEBUG_TRACE != 0)
|
||||||
void DbgOutputInit(void) {
|
void DbgOutputInit(void) {
|
||||||
}
|
}
|
||||||
@@ -353,5 +260,3 @@ void DbgOutputTraces(uint8_t* p_data, uint16_t size, void (*cb)(void)) {
|
|||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
||||||
|
|||||||
@@ -63,9 +63,10 @@ void ble_glue_init() {
|
|||||||
LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
|
LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
|
||||||
/* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */
|
/* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */
|
||||||
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
|
|
||||||
// APPD_Init();
|
#ifdef BLE_GLUE_DEBUG
|
||||||
|
APPD_Init();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialize all transport layers
|
// Initialize all transport layers
|
||||||
TL_MM_Config_t tl_mm_config;
|
TL_MM_Config_t tl_mm_config;
|
||||||
@@ -198,7 +199,6 @@ bool ble_glue_start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
if(ble_app_init()) {
|
if(ble_app_init()) {
|
||||||
FURI_LOG_I(TAG, "Radio stack started");
|
FURI_LOG_I(TAG, "Radio stack started");
|
||||||
ble_glue->status = BleGlueStatusRadioStackRunning;
|
ble_glue->status = BleGlueStatusRadioStackRunning;
|
||||||
@@ -213,7 +213,6 @@ bool ble_glue_start() {
|
|||||||
ble_glue->status = BleGlueStatusRadioStackMissing;
|
ble_glue->status = BleGlueStatusRadioStackMissing;
|
||||||
ble_app_thread_stop();
|
ble_app_thread_stop();
|
||||||
}
|
}
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -293,8 +292,10 @@ static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) {
|
|||||||
*/
|
*/
|
||||||
static void ble_glue_sys_user_event_callback(void* pPayload) {
|
static void ble_glue_sys_user_event_callback(void* pPayload) {
|
||||||
UNUSED(pPayload);
|
UNUSED(pPayload);
|
||||||
/* Traces channel initialization */
|
|
||||||
// APPD_EnableCPU2( );
|
#ifdef BLE_GLUE_DEBUG
|
||||||
|
APPD_EnableCPU2();
|
||||||
|
#endif
|
||||||
|
|
||||||
TL_AsynchEvt_t* p_sys_event =
|
TL_AsynchEvt_t* p_sys_event =
|
||||||
(TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
(TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
||||||
@@ -309,10 +310,8 @@ static void ble_glue_sys_user_event_callback(void* pPayload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ble_glue->status = BleGlueStatusC2Started;
|
ble_glue->status = BleGlueStatusC2Started;
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
} else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) {
|
} else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) {
|
||||||
FURI_LOG_E(TAG, "Error during initialization");
|
FURI_LOG_E(TAG, "Error during initialization");
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
} else if(p_sys_event->subevtcode == SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE) {
|
} else if(p_sys_event->subevtcode == SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE) {
|
||||||
SHCI_C2_BleNvmRamUpdate_Evt_t* p_sys_ble_nvm_ram_update_event =
|
SHCI_C2_BleNvmRamUpdate_Evt_t* p_sys_ble_nvm_ram_update_event =
|
||||||
(SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload;
|
(SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload;
|
||||||
@@ -444,4 +443,4 @@ BleGlueCommandResult ble_glue_fus_wait_operation() {
|
|||||||
} while(wip);
|
} while(wip);
|
||||||
|
|
||||||
return BleGlueCommandResultOK;
|
return BleGlueCommandResultOK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
|||||||
if(gap->enable_adv) {
|
if(gap->enable_adv) {
|
||||||
// Restart advertising
|
// Restart advertising
|
||||||
gap_advertise_start(GapStateAdvFast);
|
gap_advertise_start(GapStateAdvFast);
|
||||||
furi_hal_power_insomnia_exit();
|
|
||||||
}
|
}
|
||||||
GapEvent event = {.type = GapEventTypeDisconnected};
|
GapEvent event = {.type = GapEventTypeDisconnected};
|
||||||
gap->on_event_cb(event, gap->context);
|
gap->on_event_cb(event, gap->context);
|
||||||
@@ -151,8 +150,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EVT_LE_CONN_COMPLETE:
|
case EVT_LE_CONN_COMPLETE: {
|
||||||
furi_hal_power_insomnia_enter();
|
|
||||||
hci_le_connection_complete_event_rp0* event =
|
hci_le_connection_complete_event_rp0* event =
|
||||||
(hci_le_connection_complete_event_rp0*)meta_evt->data;
|
(hci_le_connection_complete_event_rp0*)meta_evt->data;
|
||||||
gap->connection_params.conn_interval = event->Conn_Interval;
|
gap->connection_params.conn_interval = event->Conn_Interval;
|
||||||
@@ -169,7 +167,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
|||||||
gap_verify_connection_parameters(gap);
|
gap_verify_connection_parameters(gap);
|
||||||
// Start pairing by sending security request
|
// Start pairing by sending security request
|
||||||
aci_gap_slave_security_req(event->Connection_Handle);
|
aci_gap_slave_security_req(event->Connection_Handle);
|
||||||
break;
|
} break;
|
||||||
|
|
||||||
case EVT_LE_ADVERTISING_REPORT: {
|
case EVT_LE_ADVERTISING_REPORT: {
|
||||||
if(gap_scan) {
|
if(gap_scan) {
|
||||||
@@ -414,7 +412,9 @@ static void gap_advertise_start(GapState new_state) {
|
|||||||
// Stop advertising
|
// Stop advertising
|
||||||
status = aci_gap_set_non_discoverable();
|
status = aci_gap_set_non_discoverable();
|
||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(TAG, "Stop Advertising Failed, result: %d", status);
|
FURI_LOG_E(TAG, "set_non_discoverable failed %d", status);
|
||||||
|
} else {
|
||||||
|
FURI_LOG_D(TAG, "set_non_discoverable success");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Configure advertising
|
// Configure advertising
|
||||||
@@ -431,7 +431,7 @@ static void gap_advertise_start(GapState new_state) {
|
|||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(TAG, "Set discoverable err: %d", status);
|
FURI_LOG_E(TAG, "set_discoverable failed %d", status);
|
||||||
}
|
}
|
||||||
gap->state = new_state;
|
gap->state = new_state;
|
||||||
GapEvent event = {.type = GapEventTypeStartAdvertising};
|
GapEvent event = {.type = GapEventTypeStartAdvertising};
|
||||||
@@ -440,14 +440,25 @@ static void gap_advertise_start(GapState new_state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void gap_advertise_stop() {
|
static void gap_advertise_stop() {
|
||||||
|
tBleStatus ret;
|
||||||
if(gap->state > GapStateIdle) {
|
if(gap->state > GapStateIdle) {
|
||||||
if(gap->state == GapStateConnected) {
|
if(gap->state == GapStateConnected) {
|
||||||
// Terminate connection
|
// Terminate connection
|
||||||
aci_gap_terminate(gap->service.connection_handle, 0x13);
|
ret = aci_gap_terminate(gap->service.connection_handle, 0x13);
|
||||||
|
if(ret != BLE_STATUS_SUCCESS) {
|
||||||
|
FURI_LOG_E(TAG, "terminate failed %d", ret);
|
||||||
|
} else {
|
||||||
|
FURI_LOG_D(TAG, "terminate success");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Stop advertising
|
// Stop advertising
|
||||||
osTimerStop(gap->advertise_timer);
|
osTimerStop(gap->advertise_timer);
|
||||||
aci_gap_set_non_discoverable();
|
ret = aci_gap_set_non_discoverable();
|
||||||
|
if(ret != BLE_STATUS_SUCCESS) {
|
||||||
|
FURI_LOG_E(TAG, "set_non_discoverable failed %d", ret);
|
||||||
|
} else {
|
||||||
|
FURI_LOG_D(TAG, "set_non_discoverable success");
|
||||||
|
}
|
||||||
gap->state = GapStateIdle;
|
gap->state = GapStateIdle;
|
||||||
}
|
}
|
||||||
GapEvent event = {.type = GapEventTypeStopAdvertising};
|
GapEvent event = {.type = GapEventTypeStopAdvertising};
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ void furi_hal_init_early() {
|
|||||||
furi_hal_clock_init_early();
|
furi_hal_clock_init_early();
|
||||||
furi_hal_delay_init();
|
furi_hal_delay_init();
|
||||||
|
|
||||||
furi_hal_os_init();
|
|
||||||
|
|
||||||
furi_hal_resources_init_early();
|
furi_hal_resources_init_early();
|
||||||
|
|
||||||
|
furi_hal_os_init();
|
||||||
|
|
||||||
furi_hal_spi_init_early();
|
furi_hal_spi_init_early();
|
||||||
|
|
||||||
furi_hal_i2c_init_early();
|
furi_hal_i2c_init_early();
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ bool furi_hal_bt_start_radio_stack() {
|
|||||||
// Wait until C2 is started or timeout
|
// Wait until C2 is started or timeout
|
||||||
if(!ble_glue_wait_for_c2_start(FURI_HAL_BT_C2_START_TIMEOUT)) {
|
if(!ble_glue_wait_for_c2_start(FURI_HAL_BT_C2_START_TIMEOUT)) {
|
||||||
FURI_LOG_E(TAG, "Core2 start failed");
|
FURI_LOG_E(TAG, "Core2 start failed");
|
||||||
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
|
||||||
ble_glue_thread_stop();
|
ble_glue_thread_stop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -154,7 +153,6 @@ bool furi_hal_bt_start_radio_stack() {
|
|||||||
// Starting radio stack
|
// Starting radio stack
|
||||||
if(!ble_glue_start()) {
|
if(!ble_glue_start()) {
|
||||||
FURI_LOG_E(TAG, "Failed to start radio stack");
|
FURI_LOG_E(TAG, "Failed to start radio stack");
|
||||||
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
|
||||||
ble_glue_thread_stop();
|
ble_glue_thread_stop();
|
||||||
ble_app_thread_stop();
|
ble_app_thread_stop();
|
||||||
break;
|
break;
|
||||||
@@ -221,27 +219,39 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void furi_hal_bt_reinit() {
|
||||||
|
FURI_LOG_I(TAG, "Disconnect and stop advertising");
|
||||||
|
furi_hal_bt_stop_advertising();
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Stop current profile services");
|
||||||
|
current_profile->stop();
|
||||||
|
|
||||||
|
// Magic happens here
|
||||||
|
hci_reset();
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Stop BLE related RTOS threads");
|
||||||
|
ble_app_thread_stop();
|
||||||
|
gap_thread_stop();
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Reset SHCI");
|
||||||
|
furi_check(ble_glue_reinit_c2());
|
||||||
|
|
||||||
|
osDelay(100);
|
||||||
|
ble_glue_thread_stop();
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Start BT initialization");
|
||||||
|
furi_hal_bt_init();
|
||||||
|
|
||||||
|
furi_hal_bt_start_radio_stack();
|
||||||
|
}
|
||||||
|
|
||||||
bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context) {
|
bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context) {
|
||||||
furi_assert(event_cb);
|
furi_assert(event_cb);
|
||||||
furi_assert(profile < FuriHalBtProfileNumber);
|
furi_assert(profile < FuriHalBtProfileNumber);
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
FURI_LOG_I(TAG, "Stop current profile services");
|
furi_hal_bt_reinit();
|
||||||
current_profile->stop();
|
|
||||||
FURI_LOG_I(TAG, "Disconnect and stop advertising");
|
|
||||||
furi_hal_bt_stop_advertising();
|
|
||||||
FURI_LOG_I(TAG, "Shutdow 2nd core");
|
|
||||||
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
|
||||||
FURI_LOG_I(TAG, "Stop BLE related RTOS threads");
|
|
||||||
ble_app_thread_stop();
|
|
||||||
gap_thread_stop();
|
|
||||||
FURI_LOG_I(TAG, "Reset SHCI");
|
|
||||||
ble_glue_reinit_c2();
|
|
||||||
osDelay(100);
|
|
||||||
ble_glue_thread_stop();
|
|
||||||
FURI_LOG_I(TAG, "Start BT initialization");
|
|
||||||
furi_hal_bt_init();
|
|
||||||
furi_hal_bt_start_radio_stack();
|
|
||||||
ret = furi_hal_bt_start_app(profile, event_cb, context);
|
ret = furi_hal_bt_start_app(profile, event_cb, context);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
current_profile = &profile_config[profile];
|
current_profile = &profile_config[profile];
|
||||||
|
|||||||
@@ -204,6 +204,8 @@ void furi_hal_clock_switch_to_hsi() {
|
|||||||
|
|
||||||
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI)
|
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
LL_FLASH_SetLatency(LL_FLASH_LATENCY_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_clock_switch_to_pll() {
|
void furi_hal_clock_switch_to_pll() {
|
||||||
@@ -215,6 +217,8 @@ void furi_hal_clock_switch_to_pll() {
|
|||||||
while(!LL_RCC_PLL_IsReady())
|
while(!LL_RCC_PLL_IsReady())
|
||||||
;
|
;
|
||||||
|
|
||||||
|
LL_FLASH_SetLatency(LL_FLASH_LATENCY_3);
|
||||||
|
|
||||||
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
|
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
|
||||||
LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSE);
|
LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSE);
|
||||||
|
|
||||||
|
|||||||
20
firmware/targets/f7/furi_hal/furi_hal_debug.c
Normal file
20
firmware/targets/f7/furi_hal/furi_hal_debug.c
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <furi_hal_debug.h>
|
||||||
|
|
||||||
|
#include <stm32wbxx_ll_exti.h>
|
||||||
|
#include <stm32wbxx_ll_system.h>
|
||||||
|
|
||||||
|
void furi_hal_debug_enable() {
|
||||||
|
// Low power mode debug
|
||||||
|
LL_DBGMCU_EnableDBGSleepMode();
|
||||||
|
LL_DBGMCU_EnableDBGStopMode();
|
||||||
|
LL_DBGMCU_EnableDBGStandbyMode();
|
||||||
|
LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48);
|
||||||
|
}
|
||||||
|
|
||||||
|
void furi_hal_debug_disable() {
|
||||||
|
// Low power mode debug
|
||||||
|
LL_DBGMCU_DisableDBGSleepMode();
|
||||||
|
LL_DBGMCU_DisableDBGStopMode();
|
||||||
|
LL_DBGMCU_DisableDBGStandbyMode();
|
||||||
|
LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_48);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <furi_hal_i2c.h>
|
#include <furi_hal_i2c.h>
|
||||||
#include <furi_hal_delay.h>
|
#include <furi_hal_delay.h>
|
||||||
#include <furi_hal_version.h>
|
#include <furi_hal_version.h>
|
||||||
|
#include <furi_hal_power.h>
|
||||||
|
|
||||||
#include <stm32wbxx_ll_i2c.h>
|
#include <stm32wbxx_ll_i2c.h>
|
||||||
#include <stm32wbxx_ll_gpio.h>
|
#include <stm32wbxx_ll_gpio.h>
|
||||||
@@ -23,6 +24,7 @@ void furi_hal_i2c_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle) {
|
void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle) {
|
||||||
|
furi_hal_power_insomnia_enter();
|
||||||
// Lock bus access
|
// Lock bus access
|
||||||
handle->bus->callback(handle->bus, FuriHalI2cBusEventLock);
|
handle->bus->callback(handle->bus, FuriHalI2cBusEventLock);
|
||||||
// Ensuree that no active handle set
|
// Ensuree that no active handle set
|
||||||
@@ -46,6 +48,7 @@ void furi_hal_i2c_release(FuriHalI2cBusHandle* handle) {
|
|||||||
handle->bus->current_handle = NULL;
|
handle->bus->current_handle = NULL;
|
||||||
// Unlock bus
|
// Unlock bus
|
||||||
handle->bus->callback(handle->bus, FuriHalI2cBusEventUnlock);
|
handle->bus->callback(handle->bus, FuriHalI2cBusEventUnlock);
|
||||||
|
furi_hal_power_insomnia_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool furi_hal_i2c_tx(
|
bool furi_hal_i2c_tx(
|
||||||
|
|||||||
@@ -7,12 +7,14 @@
|
|||||||
|
|
||||||
// Timer used for tickless idle
|
// Timer used for tickless idle
|
||||||
#define FURI_HAL_IDLE_TIMER_MAX 0xFFFF
|
#define FURI_HAL_IDLE_TIMER_MAX 0xFFFF
|
||||||
#define FURI_HAL_IDLE_TIMER LPTIM2
|
#define FURI_HAL_IDLE_TIMER LPTIM1
|
||||||
#define FURI_HAL_IDLE_TIMER_IRQ LPTIM2_IRQn
|
#define FURI_HAL_IDLE_TIMER_IRQ LPTIM1_IRQn
|
||||||
|
|
||||||
static inline void furi_hal_idle_timer_init() {
|
static inline void furi_hal_idle_timer_init() {
|
||||||
// Configure clock source
|
// Configure clock source
|
||||||
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_LSE);
|
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSE);
|
||||||
|
// There is a theoretical possibility that we need it
|
||||||
|
LL_APB1_GRP1_EnableClockSleep(LL_APB1_GRP1_PERIPH_LPTIM1);
|
||||||
// Set interrupt priority and enable them
|
// Set interrupt priority and enable them
|
||||||
NVIC_SetPriority(
|
NVIC_SetPriority(
|
||||||
FURI_HAL_IDLE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
|
FURI_HAL_IDLE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = {
|
|||||||
|
|
||||||
// HSEM
|
// HSEM
|
||||||
[FuriHalInterruptIdHsem] = HSEM_IRQn,
|
[FuriHalInterruptIdHsem] = HSEM_IRQn,
|
||||||
|
|
||||||
|
// LPTIMx
|
||||||
|
[FuriHalInterruptIdLpTim1] = LPTIM1_IRQn,
|
||||||
|
[FuriHalInterruptIdLpTim2] = LPTIM2_IRQn,
|
||||||
};
|
};
|
||||||
|
|
||||||
__attribute__((always_inline)) static inline void
|
__attribute__((always_inline)) static inline void
|
||||||
@@ -82,6 +86,16 @@ void furi_hal_interrupt_init() {
|
|||||||
|
|
||||||
NVIC_SetPriority(PendSV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
|
NVIC_SetPriority(PendSV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
|
||||||
|
|
||||||
|
NVIC_SetPriority(FPU_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
|
||||||
|
NVIC_EnableIRQ(FPU_IRQn);
|
||||||
|
|
||||||
|
LL_SYSCFG_DisableIT_FPU_IOC();
|
||||||
|
LL_SYSCFG_DisableIT_FPU_DZC();
|
||||||
|
LL_SYSCFG_DisableIT_FPU_UFC();
|
||||||
|
LL_SYSCFG_DisableIT_FPU_OFC();
|
||||||
|
LL_SYSCFG_DisableIT_FPU_IDC();
|
||||||
|
LL_SYSCFG_DisableIT_FPU_IXC();
|
||||||
|
|
||||||
FURI_LOG_I(TAG, "Init OK");
|
FURI_LOG_I(TAG, "Init OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,82 +134,82 @@ void furi_hal_interrupt_set_isr_ex(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Timer 2 */
|
/* Timer 2 */
|
||||||
void TIM2_IRQHandler(void) {
|
void TIM2_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdTIM2);
|
furi_hal_interrupt_call(FuriHalInterruptIdTIM2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Timer 1 Update */
|
/* Timer 1 Update */
|
||||||
void TIM1_UP_TIM16_IRQHandler(void) {
|
void TIM1_UP_TIM16_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdTim1UpTim16);
|
furi_hal_interrupt_call(FuriHalInterruptIdTim1UpTim16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TIM1_TRG_COM_TIM17_IRQHandler(void) {
|
void TIM1_TRG_COM_TIM17_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdTim1TrgComTim17);
|
furi_hal_interrupt_call(FuriHalInterruptIdTim1TrgComTim17);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TIM1_CC_IRQHandler(void) {
|
void TIM1_CC_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdTim1Cc);
|
furi_hal_interrupt_call(FuriHalInterruptIdTim1Cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DMA 1 */
|
/* DMA 1 */
|
||||||
void DMA1_Channel1_IRQHandler(void) {
|
void DMA1_Channel1_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch1);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA1_Channel2_IRQHandler(void) {
|
void DMA1_Channel2_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch2);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA1_Channel3_IRQHandler(void) {
|
void DMA1_Channel3_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch3);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA1_Channel4_IRQHandler(void) {
|
void DMA1_Channel4_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch4);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA1_Channel5_IRQHandler(void) {
|
void DMA1_Channel5_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch5);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA1_Channel6_IRQHandler(void) {
|
void DMA1_Channel6_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch6);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA1_Channel7_IRQHandler(void) {
|
void DMA1_Channel7_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch7);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch7);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DMA 2 */
|
/* DMA 2 */
|
||||||
void DMA2_Channel1_IRQHandler(void) {
|
void DMA2_Channel1_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch1);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA2_Channel2_IRQHandler(void) {
|
void DMA2_Channel2_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch2);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA2_Channel3_IRQHandler(void) {
|
void DMA2_Channel3_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch3);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA2_Channel4_IRQHandler(void) {
|
void DMA2_Channel4_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch4);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA2_Channel5_IRQHandler(void) {
|
void DMA2_Channel5_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch5);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA2_Channel6_IRQHandler(void) {
|
void DMA2_Channel6_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch6);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA2_Channel7_IRQHandler(void) {
|
void DMA2_Channel7_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch7);
|
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch7);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HSEM_IRQHandler(void) {
|
void HSEM_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdHsem);
|
furi_hal_interrupt_call(FuriHalInterruptIdHsem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,11 +225,11 @@ void TAMP_STAMP_LSECSS_IRQHandler(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RCC_IRQHandler(void) {
|
void RCC_IRQHandler() {
|
||||||
furi_hal_interrupt_call(FuriHalInterruptIdRcc);
|
furi_hal_interrupt_call(FuriHalInterruptIdRcc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NMI_Handler(void) {
|
void NMI_Handler() {
|
||||||
if(LL_RCC_IsActiveFlag_HSECSS()) {
|
if(LL_RCC_IsActiveFlag_HSECSS()) {
|
||||||
LL_RCC_ClearFlag_HSECSS();
|
LL_RCC_ClearFlag_HSECSS();
|
||||||
FURI_LOG_E(TAG, "HSE CSS fired: resetting system");
|
FURI_LOG_E(TAG, "HSE CSS fired: resetting system");
|
||||||
@@ -223,23 +237,23 @@ void NMI_Handler(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HardFault_Handler(void) {
|
void HardFault_Handler() {
|
||||||
furi_crash("HardFault");
|
furi_crash("HardFault");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemManage_Handler(void) {
|
void MemManage_Handler() {
|
||||||
furi_crash("MemManage");
|
furi_crash("MemManage");
|
||||||
}
|
}
|
||||||
|
|
||||||
void BusFault_Handler(void) {
|
void BusFault_Handler() {
|
||||||
furi_crash("BusFault");
|
furi_crash("BusFault");
|
||||||
}
|
}
|
||||||
|
|
||||||
void UsageFault_Handler(void) {
|
void UsageFault_Handler() {
|
||||||
furi_crash("UsageFault");
|
furi_crash("UsageFault");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugMon_Handler(void) {
|
void DebugMon_Handler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "usbd_core.h"
|
#include "usbd_core.h"
|
||||||
@@ -249,20 +263,35 @@ extern usbd_device udev;
|
|||||||
extern void HW_IPCC_Tx_Handler();
|
extern void HW_IPCC_Tx_Handler();
|
||||||
extern void HW_IPCC_Rx_Handler();
|
extern void HW_IPCC_Rx_Handler();
|
||||||
|
|
||||||
void SysTick_Handler(void) {
|
void SysTick_Handler() {
|
||||||
furi_hal_os_tick();
|
furi_hal_os_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
void USB_LP_IRQHandler(void) {
|
void USB_LP_IRQHandler() {
|
||||||
#ifndef FURI_RAM_EXEC
|
#ifndef FURI_RAM_EXEC
|
||||||
usbd_poll(&udev);
|
usbd_poll(&udev);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPCC_C1_TX_IRQHandler(void) {
|
void USB_HP_IRQHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPCC_C1_TX_IRQHandler() {
|
||||||
HW_IPCC_Tx_Handler();
|
HW_IPCC_Tx_Handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPCC_C1_RX_IRQHandler(void) {
|
void IPCC_C1_RX_IRQHandler() {
|
||||||
HW_IPCC_Rx_Handler();
|
HW_IPCC_Rx_Handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FPU_IRQHandler() {
|
||||||
|
furi_crash("FpuFault");
|
||||||
|
}
|
||||||
|
|
||||||
|
void LPTIM1_IRQHandler() {
|
||||||
|
furi_hal_interrupt_call(FuriHalInterruptIdLpTim1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LPTIM2_IRQHandler() {
|
||||||
|
furi_hal_interrupt_call(FuriHalInterruptIdLpTim2);
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ typedef enum {
|
|||||||
// HSEM
|
// HSEM
|
||||||
FuriHalInterruptIdHsem,
|
FuriHalInterruptIdHsem,
|
||||||
|
|
||||||
|
// LPTIMx
|
||||||
|
FuriHalInterruptIdLpTim1,
|
||||||
|
FuriHalInterruptIdLpTim2,
|
||||||
|
|
||||||
// Service value
|
// Service value
|
||||||
FuriHalInterruptIdMax,
|
FuriHalInterruptIdMax,
|
||||||
} FuriHalInterruptId;
|
} FuriHalInterruptId;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#include <furi_hal_os.h>
|
#include <furi_hal_os.h>
|
||||||
#include <furi_hal_clock.h>
|
#include <furi_hal_clock.h>
|
||||||
#include <furi_hal_power.h>
|
#include <furi_hal_power.h>
|
||||||
#include <furi_hal_delay.h>
|
#include <furi_hal_gpio.h>
|
||||||
|
#include <furi_hal_resources.h>
|
||||||
#include <furi_hal_idle_timer.h>
|
#include <furi_hal_idle_timer.h>
|
||||||
|
|
||||||
#include <stm32wbxx_ll_cortex.h>
|
#include <stm32wbxx_ll_cortex.h>
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
@@ -18,32 +20,32 @@
|
|||||||
#define FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH (FURI_HAL_OS_IDLE_CNT_TO_TICKS(FURI_HAL_IDLE_TIMER_MAX))
|
#define FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH (FURI_HAL_OS_IDLE_CNT_TO_TICKS(FURI_HAL_IDLE_TIMER_MAX))
|
||||||
#define FURI_HAL_OS_MAX_SLEEP (FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH - 1)
|
#define FURI_HAL_OS_MAX_SLEEP (FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH - 1)
|
||||||
|
|
||||||
|
#define FURI_HAL_OS_NVIC_IS_PENDING() (NVIC->ISPR[0] || NVIC->ISPR[1])
|
||||||
|
#define FURI_HAL_OS_EXTI_LINE_0_31 0
|
||||||
|
#define FURI_HAL_OS_EXTI_LINE_32_63 1
|
||||||
|
|
||||||
|
// Arbitrary (but small) number for better tick consistency
|
||||||
|
#define FURI_HAL_OS_EXTRA_CNT 3
|
||||||
|
|
||||||
#ifdef FURI_HAL_OS_DEBUG
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
#include <stm32wbxx_ll_gpio.h>
|
#include <stm32wbxx_ll_gpio.h>
|
||||||
|
|
||||||
#define LED_SLEEP_PORT GPIOA
|
|
||||||
#define LED_SLEEP_PIN LL_GPIO_PIN_7
|
|
||||||
#define LED_TICK_PORT GPIOA
|
|
||||||
#define LED_TICK_PIN LL_GPIO_PIN_6
|
|
||||||
#define LED_SECOND_PORT GPIOA
|
|
||||||
#define LED_SECOND_PIN LL_GPIO_PIN_4
|
|
||||||
|
|
||||||
void furi_hal_os_timer_callback() {
|
void furi_hal_os_timer_callback() {
|
||||||
LL_GPIO_TogglePin(LED_SECOND_PORT, LED_SECOND_PIN);
|
furi_hal_gpio_write(&gpio_ext_pa4, !furi_hal_gpio_read(&gpio_ext_pa4));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void xPortSysTickHandler();
|
extern void xPortSysTickHandler();
|
||||||
|
|
||||||
static volatile uint32_t furi_hal_os_skew = 0;
|
static volatile uint32_t furi_hal_os_skew;
|
||||||
|
|
||||||
void furi_hal_os_init() {
|
void furi_hal_os_init() {
|
||||||
furi_hal_idle_timer_init();
|
furi_hal_idle_timer_init();
|
||||||
|
|
||||||
#ifdef FURI_HAL_OS_DEBUG
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
LL_GPIO_SetPinMode(LED_SLEEP_PORT, LED_SLEEP_PIN, LL_GPIO_MODE_OUTPUT);
|
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull);
|
||||||
LL_GPIO_SetPinMode(LED_TICK_PORT, LED_TICK_PIN, LL_GPIO_MODE_OUTPUT);
|
furi_hal_gpio_init_simple(&gpio_ext_pa6, GpioModeOutputPushPull);
|
||||||
LL_GPIO_SetPinMode(LED_SECOND_PORT, LED_SECOND_PIN, LL_GPIO_MODE_OUTPUT);
|
furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeOutputPushPull);
|
||||||
osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL);
|
osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL);
|
||||||
osTimerStart(second_timer, FURI_HAL_OS_TICK_HZ);
|
osTimerStart(second_timer, FURI_HAL_OS_TICK_HZ);
|
||||||
#endif
|
#endif
|
||||||
@@ -54,12 +56,61 @@ void furi_hal_os_init() {
|
|||||||
void furi_hal_os_tick() {
|
void furi_hal_os_tick() {
|
||||||
if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||||
#ifdef FURI_HAL_OS_DEBUG
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
LL_GPIO_TogglePin(LED_TICK_PORT, LED_TICK_PIN);
|
furi_hal_gpio_write(&gpio_ext_pa6, !furi_hal_gpio_read(&gpio_ext_pa6));
|
||||||
#endif
|
#endif
|
||||||
xPortSysTickHandler();
|
xPortSysTickHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
|
// Find out the IRQ number while debugging
|
||||||
|
static void furi_hal_os_nvic_dbg_trap() {
|
||||||
|
for(int32_t i = WWDG_IRQn; i <= DMAMUX1_OVR_IRQn; i++) {
|
||||||
|
if(NVIC_GetPendingIRQ(i)) {
|
||||||
|
(void)i;
|
||||||
|
// Break here
|
||||||
|
__NOP();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find out the EXTI line number while debugging
|
||||||
|
static void furi_hal_os_exti_dbg_trap(uint32_t exti, uint32_t val) {
|
||||||
|
for(uint32_t i = 0; val; val >>= 1U, ++i) {
|
||||||
|
if(val & 1U) {
|
||||||
|
(void)exti;
|
||||||
|
(void)i;
|
||||||
|
// Break here
|
||||||
|
__NOP();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline bool furi_hal_os_is_pending_irq() {
|
||||||
|
if(FURI_HAL_OS_NVIC_IS_PENDING()) {
|
||||||
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
|
furi_hal_os_nvic_dbg_trap();
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t exti_lines_active;
|
||||||
|
if((exti_lines_active = LL_EXTI_ReadFlag_0_31(LL_EXTI_LINE_ALL_0_31))) {
|
||||||
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
|
furi_hal_os_exti_dbg_trap(FURI_HAL_OS_EXTI_LINE_0_31, exti_lines_active);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
} else if((exti_lines_active = LL_EXTI_ReadFlag_32_63(LL_EXTI_LINE_ALL_32_63))) {
|
||||||
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
|
furi_hal_os_exti_dbg_trap(FURI_HAL_OS_EXTI_LINE_32_63, exti_lines_active);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) {
|
static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) {
|
||||||
// Stop ticks
|
// Stop ticks
|
||||||
furi_hal_clock_suspend_tick();
|
furi_hal_clock_suspend_tick();
|
||||||
@@ -68,20 +119,20 @@ static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) {
|
|||||||
furi_hal_idle_timer_start(FURI_HAL_OS_TICKS_TO_IDLE_CNT(expected_idle_ticks));
|
furi_hal_idle_timer_start(FURI_HAL_OS_TICKS_TO_IDLE_CNT(expected_idle_ticks));
|
||||||
|
|
||||||
#ifdef FURI_HAL_OS_DEBUG
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
LL_GPIO_ResetOutputPin(LED_SLEEP_PORT, LED_SLEEP_PIN);
|
furi_hal_gpio_write(&gpio_ext_pa7, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Go to sleep mode
|
// Go to sleep mode
|
||||||
furi_hal_power_sleep();
|
furi_hal_power_sleep();
|
||||||
|
|
||||||
#ifdef FURI_HAL_OS_DEBUG
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
LL_GPIO_SetOutputPin(LED_SLEEP_PORT, LED_SLEEP_PIN);
|
furi_hal_gpio_write(&gpio_ext_pa7, 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Calculate how much time we spent in the sleep
|
// Calculate how much time we spent in the sleep
|
||||||
uint32_t after_cnt = furi_hal_idle_timer_get_cnt() + furi_hal_os_skew;
|
uint32_t after_cnt = furi_hal_idle_timer_get_cnt() + furi_hal_os_skew + FURI_HAL_OS_EXTRA_CNT;
|
||||||
uint32_t after_tick = FURI_HAL_OS_IDLE_CNT_TO_TICKS(after_cnt);
|
uint32_t after_tick = FURI_HAL_OS_IDLE_CNT_TO_TICKS(after_cnt);
|
||||||
furi_hal_os_skew = after_cnt - (after_cnt / after_tick);
|
furi_hal_os_skew = after_cnt - FURI_HAL_OS_TICKS_TO_IDLE_CNT(after_tick);
|
||||||
|
|
||||||
bool cmpm = LL_LPTIM_IsActiveFlag_CMPM(FURI_HAL_IDLE_TIMER);
|
bool cmpm = LL_LPTIM_IsActiveFlag_CMPM(FURI_HAL_IDLE_TIMER);
|
||||||
bool arrm = LL_LPTIM_IsActiveFlag_ARRM(FURI_HAL_IDLE_TIMER);
|
bool arrm = LL_LPTIM_IsActiveFlag_ARRM(FURI_HAL_IDLE_TIMER);
|
||||||
@@ -110,7 +161,7 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
|
|||||||
__disable_irq();
|
__disable_irq();
|
||||||
|
|
||||||
// Confirm OS that sleep is still possible
|
// Confirm OS that sleep is still possible
|
||||||
if(eTaskConfirmSleepModeStatus() == eAbortSleep) {
|
if(eTaskConfirmSleepModeStatus() == eAbortSleep || furi_hal_os_is_pending_irq()) {
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <furi_hal_clock.h>
|
#include <furi_hal_clock.h>
|
||||||
#include <furi_hal_bt.h>
|
#include <furi_hal_bt.h>
|
||||||
#include <furi_hal_resources.h>
|
#include <furi_hal_resources.h>
|
||||||
|
#include <furi_hal_uart.h>
|
||||||
|
|
||||||
#include <stm32wbxx_ll_rcc.h>
|
#include <stm32wbxx_ll_rcc.h>
|
||||||
#include <stm32wbxx_ll_pwr.h>
|
#include <stm32wbxx_ll_pwr.h>
|
||||||
@@ -17,6 +18,12 @@
|
|||||||
|
|
||||||
#define TAG "FuriHalPower"
|
#define TAG "FuriHalPower"
|
||||||
|
|
||||||
|
#ifdef FURI_HAL_POWER_DEEP_SLEEP_ENABLED
|
||||||
|
#define FURI_HAL_POWER_DEEP_INSOMNIA 0
|
||||||
|
#else
|
||||||
|
#define FURI_HAL_POWER_DEEP_INSOMNIA 1
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
volatile uint8_t insomnia;
|
volatile uint8_t insomnia;
|
||||||
volatile uint8_t deep_insomnia;
|
volatile uint8_t deep_insomnia;
|
||||||
@@ -28,7 +35,7 @@ typedef struct {
|
|||||||
|
|
||||||
static volatile FuriHalPower furi_hal_power = {
|
static volatile FuriHalPower furi_hal_power = {
|
||||||
.insomnia = 0,
|
.insomnia = 0,
|
||||||
.deep_insomnia = 1,
|
.deep_insomnia = FURI_HAL_POWER_DEEP_INSOMNIA,
|
||||||
.suppress_charge = 0,
|
.suppress_charge = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -70,11 +77,6 @@ const ParamCEDV cedv = {
|
|||||||
.DOD100 = 3299,
|
.DOD100 = 3299,
|
||||||
};
|
};
|
||||||
|
|
||||||
void HAL_RCC_CSSCallback(void) {
|
|
||||||
// TODO: notify user about issue with HSE
|
|
||||||
furi_hal_power_reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_power_init() {
|
void furi_hal_power_init() {
|
||||||
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
|
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
|
||||||
LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN);
|
LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN);
|
||||||
@@ -84,6 +86,11 @@ void furi_hal_power_init() {
|
|||||||
bq25896_init(&furi_hal_i2c_handle_power);
|
bq25896_init(&furi_hal_i2c_handle_power);
|
||||||
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||||
|
|
||||||
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
|
furi_hal_gpio_init_simple(&gpio_ext_pb2, GpioModeOutputPushPull);
|
||||||
|
furi_hal_gpio_init_simple(&gpio_ext_pc3, GpioModeOutputPushPull);
|
||||||
|
#endif
|
||||||
|
|
||||||
FURI_LOG_I(TAG, "Init OK");
|
FURI_LOG_I(TAG, "Init OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,12 +147,28 @@ void furi_hal_power_light_sleep() {
|
|||||||
__WFI();
|
__WFI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void furi_hal_power_suspend_aux_periphs() {
|
||||||
|
// Disable USART
|
||||||
|
furi_hal_uart_suspend(FuriHalUartIdUSART1);
|
||||||
|
furi_hal_uart_suspend(FuriHalUartIdLPUART1);
|
||||||
|
// TODO: Disable USB
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void furi_hal_power_resume_aux_periphs() {
|
||||||
|
// Re-enable USART
|
||||||
|
furi_hal_uart_resume(FuriHalUartIdUSART1);
|
||||||
|
furi_hal_uart_resume(FuriHalUartIdLPUART1);
|
||||||
|
// TODO: Re-enable USB
|
||||||
|
}
|
||||||
|
|
||||||
void furi_hal_power_deep_sleep() {
|
void furi_hal_power_deep_sleep() {
|
||||||
|
furi_hal_power_suspend_aux_periphs();
|
||||||
|
|
||||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID))
|
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID))
|
||||||
;
|
;
|
||||||
|
|
||||||
if(!LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) {
|
if(!LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) {
|
||||||
if(LL_PWR_IsActiveFlag_C2DS()) {
|
if(LL_PWR_IsActiveFlag_C2DS() || LL_PWR_IsActiveFlag_C2SB()) {
|
||||||
// Release ENTRY_STOP_MODE semaphore
|
// Release ENTRY_STOP_MODE semaphore
|
||||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
||||||
|
|
||||||
@@ -163,7 +186,8 @@ void furi_hal_power_deep_sleep() {
|
|||||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
||||||
|
|
||||||
// Prepare deep sleep
|
// Prepare deep sleep
|
||||||
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP1);
|
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2);
|
||||||
|
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2);
|
||||||
LL_LPM_EnableDeepSleep();
|
LL_LPM_EnableDeepSleep();
|
||||||
|
|
||||||
#if defined(__CC_ARM)
|
#if defined(__CC_ARM)
|
||||||
@@ -173,6 +197,15 @@ void furi_hal_power_deep_sleep() {
|
|||||||
|
|
||||||
__WFI();
|
__WFI();
|
||||||
|
|
||||||
|
LL_LPM_EnableSleep();
|
||||||
|
|
||||||
|
// Make sure that values differ to prevent disaster on wfi
|
||||||
|
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0);
|
||||||
|
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
||||||
|
|
||||||
|
LL_PWR_ClearFlag_C1STOP_C1STB();
|
||||||
|
LL_PWR_ClearFlag_C2STOP_C2STB();
|
||||||
|
|
||||||
/* Release ENTRY_STOP_MODE semaphore */
|
/* Release ENTRY_STOP_MODE semaphore */
|
||||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
||||||
|
|
||||||
@@ -184,13 +217,31 @@ void furi_hal_power_deep_sleep() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
||||||
|
|
||||||
|
furi_hal_power_resume_aux_periphs();
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_power_sleep() {
|
void furi_hal_power_sleep() {
|
||||||
if(furi_hal_power_deep_sleep_available()) {
|
if(furi_hal_power_deep_sleep_available()) {
|
||||||
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
|
furi_hal_gpio_write(&gpio_ext_pc3, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
furi_hal_power_deep_sleep();
|
furi_hal_power_deep_sleep();
|
||||||
|
|
||||||
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
|
furi_hal_gpio_write(&gpio_ext_pc3, 0);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
|
furi_hal_gpio_write(&gpio_ext_pb2, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
furi_hal_power_light_sleep();
|
furi_hal_power_light_sleep();
|
||||||
|
|
||||||
|
#ifdef FURI_HAL_OS_DEBUG
|
||||||
|
furi_hal_gpio_write(&gpio_ext_pb2, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +266,38 @@ bool furi_hal_power_is_charging() {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void furi_hal_power_shutdown() {
|
||||||
|
furi_hal_power_insomnia_enter();
|
||||||
|
|
||||||
|
furi_hal_bt_reinit();
|
||||||
|
|
||||||
|
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID))
|
||||||
|
;
|
||||||
|
|
||||||
|
if(!LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) {
|
||||||
|
if(LL_PWR_IsActiveFlag_C2DS() || LL_PWR_IsActiveFlag_C2SB()) {
|
||||||
|
// Release ENTRY_STOP_MODE semaphore
|
||||||
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare Wakeup pin
|
||||||
|
LL_PWR_SetWakeUpPinPolarityLow(LL_PWR_WAKEUP_PIN2);
|
||||||
|
LL_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN2);
|
||||||
|
LL_C2_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN2);
|
||||||
|
|
||||||
|
/* Release RCC semaphore */
|
||||||
|
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
|
||||||
|
|
||||||
|
LL_PWR_DisableBootC2();
|
||||||
|
LL_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
||||||
|
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
||||||
|
LL_LPM_EnableDeepSleep();
|
||||||
|
|
||||||
|
__WFI();
|
||||||
|
furi_crash("Insomniac core2");
|
||||||
|
}
|
||||||
|
|
||||||
void furi_hal_power_off() {
|
void furi_hal_power_off() {
|
||||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||||
bq25896_poweroff(&furi_hal_i2c_handle_power);
|
bq25896_poweroff(&furi_hal_i2c_handle_power);
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include <furi_hal_resources.h>
|
#include <furi_hal_resources.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
|
#include <stm32wbxx_ll_rcc.h>
|
||||||
|
#include <stm32wbxx_ll_pwr.h>
|
||||||
|
|
||||||
const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin};
|
const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin};
|
||||||
const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin};
|
const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin};
|
||||||
|
|
||||||
@@ -9,7 +12,7 @@ const GpioPin gpio_rf_sw_0 = {.port = RF_SW_0_GPIO_Port, .pin = RF_SW_0_Pin};
|
|||||||
|
|
||||||
const GpioPin gpio_subghz_cs = {.port = CC1101_CS_GPIO_Port, .pin = CC1101_CS_Pin};
|
const GpioPin gpio_subghz_cs = {.port = CC1101_CS_GPIO_Port, .pin = CC1101_CS_Pin};
|
||||||
const GpioPin gpio_display_cs = {.port = DISPLAY_CS_GPIO_Port, .pin = DISPLAY_CS_Pin};
|
const GpioPin gpio_display_cs = {.port = DISPLAY_CS_GPIO_Port, .pin = DISPLAY_CS_Pin};
|
||||||
const GpioPin gpio_display_rst = {.port = DISPLAY_RST_GPIO_Port, .pin = DISPLAY_RST_Pin};
|
const GpioPin gpio_display_rst_n = {.port = DISPLAY_RST_GPIO_Port, .pin = DISPLAY_RST_Pin};
|
||||||
const GpioPin gpio_display_di = {.port = DISPLAY_DI_GPIO_Port, .pin = DISPLAY_DI_Pin};
|
const GpioPin gpio_display_di = {.port = DISPLAY_DI_GPIO_Port, .pin = DISPLAY_DI_Pin};
|
||||||
const GpioPin gpio_sdcard_cs = {.port = SD_CS_GPIO_Port, .pin = SD_CS_Pin};
|
const GpioPin gpio_sdcard_cs = {.port = SD_CS_GPIO_Port, .pin = SD_CS_Pin};
|
||||||
const GpioPin gpio_sdcard_cd = {.port = SD_CD_GPIO_Port, .pin = SD_CD_Pin};
|
const GpioPin gpio_sdcard_cd = {.port = SD_CD_GPIO_Port, .pin = SD_CD_Pin};
|
||||||
@@ -72,14 +75,32 @@ const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin);
|
|||||||
|
|
||||||
void furi_hal_resources_init_early() {
|
void furi_hal_resources_init_early() {
|
||||||
furi_hal_gpio_init(&gpio_button_left, GpioModeInput, GpioPullUp, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_button_left, GpioModeInput, GpioPullUp, GpioSpeedLow);
|
||||||
furi_hal_gpio_init_simple(&gpio_display_rst, GpioModeOutputPushPull);
|
|
||||||
|
// Display pins
|
||||||
|
furi_hal_gpio_write(&gpio_display_rst_n, 1);
|
||||||
|
furi_hal_gpio_init_simple(&gpio_display_rst_n, GpioModeOutputPushPull);
|
||||||
furi_hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull);
|
furi_hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull);
|
||||||
|
|
||||||
|
// Alternative pull configuration for shutdown
|
||||||
|
SET_BIT(PWR->PUCRB, DISPLAY_RST_Pin);
|
||||||
|
CLEAR_BIT(PWR->PDCRB, DISPLAY_RST_Pin);
|
||||||
|
SET_BIT(PWR->CR3, PWR_CR3_APC);
|
||||||
|
|
||||||
// Hard reset USB
|
// Hard reset USB
|
||||||
furi_hal_gpio_init_simple(&gpio_usb_dm, GpioModeOutputOpenDrain);
|
furi_hal_gpio_init_simple(&gpio_usb_dm, GpioModeOutputOpenDrain);
|
||||||
furi_hal_gpio_init_simple(&gpio_usb_dp, GpioModeOutputOpenDrain);
|
furi_hal_gpio_init_simple(&gpio_usb_dp, GpioModeOutputOpenDrain);
|
||||||
furi_hal_gpio_write(&gpio_usb_dm, 0);
|
furi_hal_gpio_write(&gpio_usb_dm, 0);
|
||||||
furi_hal_gpio_write(&gpio_usb_dp, 0);
|
furi_hal_gpio_write(&gpio_usb_dp, 0);
|
||||||
|
|
||||||
|
// External header pins
|
||||||
|
furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(&gpio_ext_pb2, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(&gpio_ext_pa6, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_resources_deinit_early() {
|
void furi_hal_resources_deinit_early() {
|
||||||
@@ -92,19 +113,9 @@ void furi_hal_resources_init() {
|
|||||||
input_pins[i].gpio, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedLow);
|
input_pins[i].gpio, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedLow);
|
||||||
}
|
}
|
||||||
|
|
||||||
// External header pins
|
|
||||||
furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
|
||||||
furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
|
||||||
furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
|
||||||
furi_hal_gpio_init(&gpio_ext_pb2, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
|
||||||
furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
|
||||||
furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
|
||||||
furi_hal_gpio_init(&gpio_ext_pa6, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
|
||||||
furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
|
||||||
|
|
||||||
// Display pins
|
// Display pins
|
||||||
furi_hal_gpio_init(&gpio_display_rst, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_display_rst_n, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||||
furi_hal_gpio_write(&gpio_display_rst, 0);
|
furi_hal_gpio_write(&gpio_display_rst_n, 0);
|
||||||
|
|
||||||
furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||||
furi_hal_gpio_write(&gpio_display_di, 0);
|
furi_hal_gpio_write(&gpio_display_di, 0);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ extern const GpioPin gpio_rf_sw_0;
|
|||||||
|
|
||||||
extern const GpioPin gpio_subghz_cs;
|
extern const GpioPin gpio_subghz_cs;
|
||||||
extern const GpioPin gpio_display_cs;
|
extern const GpioPin gpio_display_cs;
|
||||||
extern const GpioPin gpio_display_rst;
|
extern const GpioPin gpio_display_rst_n;
|
||||||
extern const GpioPin gpio_display_di;
|
extern const GpioPin gpio_display_di;
|
||||||
extern const GpioPin gpio_sdcard_cs;
|
extern const GpioPin gpio_sdcard_cs;
|
||||||
extern const GpioPin gpio_sdcard_cd;
|
extern const GpioPin gpio_sdcard_cd;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <furi_hal_rtc.h>
|
#include <furi_hal_rtc.h>
|
||||||
#include <furi_hal_light.h>
|
#include <furi_hal_light.h>
|
||||||
|
#include <furi_hal_debug.h>
|
||||||
|
|
||||||
#include <stm32wbxx_ll_bus.h>
|
#include <stm32wbxx_ll_bus.h>
|
||||||
#include <stm32wbxx_ll_pwr.h>
|
#include <stm32wbxx_ll_pwr.h>
|
||||||
@@ -36,7 +37,6 @@ void furi_hal_rtc_init_early() {
|
|||||||
// LSE and RTC
|
// LSE and RTC
|
||||||
LL_PWR_EnableBkUpAccess();
|
LL_PWR_EnableBkUpAccess();
|
||||||
if(!RTC_CLOCK_IS_READY()) {
|
if(!RTC_CLOCK_IS_READY()) {
|
||||||
// Start LSI1 needed for CSS
|
|
||||||
LL_RCC_LSI1_Enable();
|
LL_RCC_LSI1_Enable();
|
||||||
// Try to start LSE normal way
|
// Try to start LSE normal way
|
||||||
LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_HIGH);
|
LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_HIGH);
|
||||||
@@ -55,8 +55,6 @@ void furi_hal_rtc_init_early() {
|
|||||||
}
|
}
|
||||||
// Set RTC domain clock to LSE
|
// Set RTC domain clock to LSE
|
||||||
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
|
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
|
||||||
// Enable LSE CSS
|
|
||||||
LL_RCC_LSE_EnableCSS();
|
|
||||||
}
|
}
|
||||||
// Enable clocking
|
// Enable clocking
|
||||||
LL_RCC_EnableRTC();
|
LL_RCC_EnableRTC();
|
||||||
@@ -74,6 +72,12 @@ void furi_hal_rtc_init_early() {
|
|||||||
data->version = FURI_HAL_RTC_HEADER_VERSION;
|
data->version = FURI_HAL_RTC_HEADER_VERSION;
|
||||||
furi_hal_rtc_set_register(FuriHalRtcRegisterHeader, data_reg);
|
furi_hal_rtc_set_register(FuriHalRtcRegisterHeader, data_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||||
|
furi_hal_debug_enable();
|
||||||
|
} else {
|
||||||
|
furi_hal_debug_disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_rtc_deinit_early() {
|
void furi_hal_rtc_deinit_early() {
|
||||||
@@ -126,6 +130,10 @@ void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) {
|
|||||||
DeveloperReg* data = (DeveloperReg*)&data_reg;
|
DeveloperReg* data = (DeveloperReg*)&data_reg;
|
||||||
data->flags |= flag;
|
data->flags |= flag;
|
||||||
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
|
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
|
||||||
|
|
||||||
|
if(flag & FuriHalRtcFlagDebug) {
|
||||||
|
furi_hal_debug_enable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) {
|
void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) {
|
||||||
@@ -133,6 +141,10 @@ void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) {
|
|||||||
DeveloperReg* data = (DeveloperReg*)&data_reg;
|
DeveloperReg* data = (DeveloperReg*)&data_reg;
|
||||||
data->flags &= ~flag;
|
data->flags &= ~flag;
|
||||||
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
|
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
|
||||||
|
|
||||||
|
if(flag & FuriHalRtcFlagDebug) {
|
||||||
|
furi_hal_debug_disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) {
|
bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "furi_hal_spi.h"
|
#include "furi_hal_spi.h"
|
||||||
#include "furi_hal_resources.h"
|
#include "furi_hal_resources.h"
|
||||||
|
#include <furi_hal_power.h>
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -55,6 +56,8 @@ void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) {
|
|||||||
void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) {
|
void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) {
|
||||||
furi_assert(handle);
|
furi_assert(handle);
|
||||||
|
|
||||||
|
furi_hal_power_insomnia_enter();
|
||||||
|
|
||||||
handle->bus->callback(handle->bus, FuriHalSpiBusEventLock);
|
handle->bus->callback(handle->bus, FuriHalSpiBusEventLock);
|
||||||
handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate);
|
handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate);
|
||||||
|
|
||||||
@@ -75,6 +78,8 @@ void furi_hal_spi_release(FuriHalSpiBusHandle* handle) {
|
|||||||
// Bus events
|
// Bus events
|
||||||
handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate);
|
handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate);
|
||||||
handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock);
|
handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock);
|
||||||
|
|
||||||
|
furi_hal_power_insomnia_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) {
|
static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal_delay.h>
|
#include <furi_hal_delay.h>
|
||||||
|
|
||||||
|
static bool furi_hal_usart_prev_enabled[2];
|
||||||
|
|
||||||
static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context);
|
static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context);
|
||||||
static void* irq_ctx[2];
|
static void* irq_ctx[2];
|
||||||
|
|
||||||
@@ -44,7 +46,6 @@ static void furi_hal_usart_init(uint32_t baud) {
|
|||||||
;
|
;
|
||||||
|
|
||||||
LL_USART_EnableIT_RXNE_RXFNE(USART1);
|
LL_USART_EnableIT_RXNE_RXFNE(USART1);
|
||||||
LL_USART_EnableIT_IDLE(USART1);
|
|
||||||
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +82,6 @@ static void furi_hal_lpuart_init(uint32_t baud) {
|
|||||||
furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud);
|
furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud);
|
||||||
|
|
||||||
LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
|
LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
|
||||||
LL_LPUART_EnableIT_IDLE(LPUART1);
|
|
||||||
NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +136,28 @@ void furi_hal_uart_deinit(FuriHalUartId ch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void furi_hal_uart_suspend(FuriHalUartId channel) {
|
||||||
|
if(channel == FuriHalUartIdLPUART1 && LL_LPUART_IsEnabled(LPUART1)) {
|
||||||
|
LL_LPUART_Disable(LPUART1);
|
||||||
|
furi_hal_usart_prev_enabled[channel] = true;
|
||||||
|
} else if(channel == FuriHalUartIdUSART1 && LL_USART_IsEnabled(USART1)) {
|
||||||
|
LL_USART_Disable(USART1);
|
||||||
|
furi_hal_usart_prev_enabled[channel] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void furi_hal_uart_resume(FuriHalUartId channel) {
|
||||||
|
if(!furi_hal_usart_prev_enabled[channel]) {
|
||||||
|
return;
|
||||||
|
} else if(channel == FuriHalUartIdLPUART1) {
|
||||||
|
LL_LPUART_Enable(LPUART1);
|
||||||
|
} else if(channel == FuriHalUartIdUSART1) {
|
||||||
|
LL_USART_Enable(USART1);
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_hal_usart_prev_enabled[channel] = false;
|
||||||
|
}
|
||||||
|
|
||||||
void furi_hal_uart_tx(FuriHalUartId ch, uint8_t* buffer, size_t buffer_size) {
|
void furi_hal_uart_tx(FuriHalUartId ch, uint8_t* buffer, size_t buffer_size) {
|
||||||
if(ch == FuriHalUartIdUSART1) {
|
if(ch == FuriHalUartIdUSART1) {
|
||||||
if(LL_USART_IsEnabled(USART1) == 0) return;
|
if(LL_USART_IsEnabled(USART1) == 0) return;
|
||||||
@@ -189,22 +211,15 @@ void LPUART1_IRQHandler(void) {
|
|||||||
if(LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) {
|
if(LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) {
|
||||||
uint8_t data = LL_LPUART_ReceiveData8(LPUART1);
|
uint8_t data = LL_LPUART_ReceiveData8(LPUART1);
|
||||||
irq_cb[FuriHalUartIdLPUART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdLPUART1]);
|
irq_cb[FuriHalUartIdLPUART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdLPUART1]);
|
||||||
} else if(LL_LPUART_IsActiveFlag_IDLE(LPUART1)) {
|
|
||||||
irq_cb[FuriHalUartIdLPUART1](UartIrqEventIDLE, 0, irq_ctx[FuriHalUartIdLPUART1]);
|
|
||||||
LL_LPUART_ClearFlag_IDLE(LPUART1);
|
|
||||||
} else if(LL_LPUART_IsActiveFlag_ORE(LPUART1)) {
|
} else if(LL_LPUART_IsActiveFlag_ORE(LPUART1)) {
|
||||||
LL_LPUART_ClearFlag_ORE(LPUART1);
|
LL_LPUART_ClearFlag_ORE(LPUART1);
|
||||||
}
|
}
|
||||||
//TODO: more events
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void USART1_IRQHandler(void) {
|
void USART1_IRQHandler(void) {
|
||||||
if(LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) {
|
if(LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) {
|
||||||
uint8_t data = LL_USART_ReceiveData8(USART1);
|
uint8_t data = LL_USART_ReceiveData8(USART1);
|
||||||
irq_cb[FuriHalUartIdUSART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdUSART1]);
|
irq_cb[FuriHalUartIdUSART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdUSART1]);
|
||||||
} else if(LL_USART_IsActiveFlag_IDLE(USART1)) {
|
|
||||||
irq_cb[FuriHalUartIdUSART1](UartIrqEventIDLE, 0, irq_ctx[FuriHalUartIdUSART1]);
|
|
||||||
LL_USART_ClearFlag_IDLE(USART1);
|
|
||||||
} else if(LL_USART_IsActiveFlag_ORE(USART1)) {
|
} else if(LL_USART_IsActiveFlag_ORE(USART1)) {
|
||||||
LL_USART_ClearFlag_ORE(USART1);
|
LL_USART_ClearFlag_ORE(USART1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UartIrqEventRXNE,
|
UartIrqEventRXNE,
|
||||||
UartIrqEventIDLE,
|
|
||||||
//TODO: more events
|
|
||||||
} UartIrqEvent;
|
} UartIrqEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,6 +44,20 @@ void furi_hal_uart_init(FuriHalUartId channel, uint32_t baud);
|
|||||||
*/
|
*/
|
||||||
void furi_hal_uart_deinit(FuriHalUartId channel);
|
void furi_hal_uart_deinit(FuriHalUartId channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suspend UART operation
|
||||||
|
* Disables UART hardware, settings and callbacks are preserved
|
||||||
|
* @param channel UART channel
|
||||||
|
*/
|
||||||
|
void furi_hal_uart_suspend(FuriHalUartId channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resume UART operation
|
||||||
|
* Resumes UART hardware from suspended state
|
||||||
|
* @param channel UART channel
|
||||||
|
*/
|
||||||
|
void furi_hal_uart_resume(FuriHalUartId channel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes UART baudrate
|
* Changes UART baudrate
|
||||||
* @param channel UART channel
|
* @param channel UART channel
|
||||||
@@ -74,4 +86,4 @@ void furi_hal_uart_set_irq_cb(
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "furi_hal_version.h"
|
#include "furi_hal_version.h"
|
||||||
#include "furi_hal_usb_i.h"
|
#include "furi_hal_usb_i.h"
|
||||||
#include "furi_hal_usb.h"
|
#include "furi_hal_usb.h"
|
||||||
#include "furi_hal_vcp.h"
|
|
||||||
#include <furi_hal_power.h>
|
#include <furi_hal_power.h>
|
||||||
#include <stm32wbxx_ll_pwr.h>
|
#include <stm32wbxx_ll_pwr.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
@@ -77,7 +76,9 @@ void furi_hal_usb_init(void) {
|
|||||||
usb.enabled = false;
|
usb.enabled = false;
|
||||||
usb.if_cur = NULL;
|
usb.if_cur = NULL;
|
||||||
NVIC_SetPriority(USB_LP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
NVIC_SetPriority(USB_LP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||||
|
NVIC_SetPriority(USB_HP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
|
||||||
NVIC_EnableIRQ(USB_LP_IRQn);
|
NVIC_EnableIRQ(USB_LP_IRQn);
|
||||||
|
NVIC_EnableIRQ(USB_HP_IRQn);
|
||||||
|
|
||||||
usb.thread = furi_thread_alloc();
|
usb.thread = furi_thread_alloc();
|
||||||
furi_thread_set_name(usb.thread, "UsbDriver");
|
furi_thread_set_name(usb.thread, "UsbDriver");
|
||||||
|
|||||||
@@ -482,6 +482,9 @@ void furi_hal_cdc_set_callbacks(uint8_t if_num, CdcCallbacks* cb, void* context)
|
|||||||
if(callbacks[if_num]->state_callback != NULL) {
|
if(callbacks[if_num]->state_callback != NULL) {
|
||||||
if(connected == true) callbacks[if_num]->state_callback(cb_ctx[if_num], 1);
|
if(connected == true) callbacks[if_num]->state_callback(cb_ctx[if_num], 1);
|
||||||
}
|
}
|
||||||
|
if(callbacks[if_num]->ctrl_line_callback != NULL) {
|
||||||
|
callbacks[if_num]->ctrl_line_callback(cb_ctx[if_num], cdc_ctrl_line_state[if_num]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,10 @@ ifeq ($(FURI_HAL_USB_VCP_DEBUG), 1)
|
|||||||
CFLAGS += -DFURI_HAL_USB_VCP_DEBUG
|
CFLAGS += -DFURI_HAL_USB_VCP_DEBUG
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(FURI_HAL_POWER_DEEP_SLEEP_ENABLED), 1)
|
||||||
|
CFLAGS += -DFURI_HAL_POWER_DEEP_SLEEP_ENABLED
|
||||||
|
endif
|
||||||
|
|
||||||
FURI_HAL_SUBGHZ_TX_GPIO ?= 0
|
FURI_HAL_SUBGHZ_TX_GPIO ?= 0
|
||||||
ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0)
|
ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0)
|
||||||
CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO)
|
CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO)
|
||||||
@@ -128,6 +132,10 @@ ifeq ($(INVERT_RFID_IN), 1)
|
|||||||
CFLAGS += -DINVERT_RFID_IN
|
CFLAGS += -DINVERT_RFID_IN
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(BLE_GLUE_DEBUG), 1)
|
||||||
|
CFLAGS += -DBLE_GLUE_DEBUG
|
||||||
|
endif
|
||||||
|
|
||||||
FURI_HAL_DIR = $(TARGET_DIR)/furi_hal
|
FURI_HAL_DIR = $(TARGET_DIR)/furi_hal
|
||||||
CFLAGS += -I$(FURI_HAL_DIR)
|
CFLAGS += -I$(FURI_HAL_DIR)
|
||||||
C_SOURCES += $(wildcard $(FURI_HAL_DIR)/*.c)
|
C_SOURCES += $(wildcard $(FURI_HAL_DIR)/*.c)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ template <unsigned int N> struct STOP_EXTERNING_ME {};
|
|||||||
#include "furi_hal_clock.h"
|
#include "furi_hal_clock.h"
|
||||||
#include "furi_hal_crypto.h"
|
#include "furi_hal_crypto.h"
|
||||||
#include "furi_hal_console.h"
|
#include "furi_hal_console.h"
|
||||||
|
#include "furi_hal_debug.h"
|
||||||
#include "furi_hal_os.h"
|
#include "furi_hal_os.h"
|
||||||
#include "furi_hal_sd.h"
|
#include "furi_hal_sd.h"
|
||||||
#include "furi_hal_i2c.h"
|
#include "furi_hal_i2c.h"
|
||||||
@@ -22,7 +23,6 @@ template <unsigned int N> struct STOP_EXTERNING_ME {};
|
|||||||
#include "furi_hal_light.h"
|
#include "furi_hal_light.h"
|
||||||
#include "furi_hal_delay.h"
|
#include "furi_hal_delay.h"
|
||||||
#include "furi_hal_power.h"
|
#include "furi_hal_power.h"
|
||||||
#include "furi_hal_vcp.h"
|
|
||||||
#include "furi_hal_interrupt.h"
|
#include "furi_hal_interrupt.h"
|
||||||
#include "furi_hal_version.h"
|
#include "furi_hal_version.h"
|
||||||
#include "furi_hal_bt.h"
|
#include "furi_hal_bt.h"
|
||||||
|
|||||||
@@ -68,6 +68,12 @@ FuriHalBtStack furi_hal_bt_get_radio_stack();
|
|||||||
*/
|
*/
|
||||||
bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context);
|
bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context);
|
||||||
|
|
||||||
|
/** Reinitialize core2
|
||||||
|
*
|
||||||
|
* Also can be used to prepare core2 for stop modes
|
||||||
|
*/
|
||||||
|
void furi_hal_bt_reinit();
|
||||||
|
|
||||||
/** Change BLE app
|
/** Change BLE app
|
||||||
* Restarts 2nd core
|
* Restarts 2nd core
|
||||||
*
|
*
|
||||||
|
|||||||
23
firmware/targets/furi_hal_include/furi_hal_debug.h
Normal file
23
firmware/targets/furi_hal_include/furi_hal_debug.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* @file furi_hal_debug.h
|
||||||
|
* Debug HAL API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Enable MCU debug */
|
||||||
|
void furi_hal_debug_enable();
|
||||||
|
|
||||||
|
/** Disable MCU debug */
|
||||||
|
void furi_hal_debug_disable();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -85,6 +85,9 @@ uint8_t furi_hal_power_get_bat_health_pct();
|
|||||||
*/
|
*/
|
||||||
bool furi_hal_power_is_charging();
|
bool furi_hal_power_is_charging();
|
||||||
|
|
||||||
|
/** Switch MCU to SHUTDOWN */
|
||||||
|
void furi_hal_power_shutdown();
|
||||||
|
|
||||||
/** Poweroff device
|
/** Poweroff device
|
||||||
*/
|
*/
|
||||||
void furi_hal_power_off();
|
void furi_hal_power_off();
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file furi_hal_vcp.h
|
|
||||||
* VCP HAL API
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Init VCP HAL Allocates ring buffer and initializes state
|
|
||||||
*/
|
|
||||||
void furi_hal_vcp_init();
|
|
||||||
|
|
||||||
/** Disable VCP to make CDC interface usable by other application
|
|
||||||
*/
|
|
||||||
void furi_hal_vcp_disable();
|
|
||||||
|
|
||||||
/** Enable VCP
|
|
||||||
*/
|
|
||||||
void furi_hal_vcp_enable();
|
|
||||||
|
|
||||||
/** Recieve data from VCP Waits till some data arrives, never returns 0
|
|
||||||
*
|
|
||||||
* @param buffer pointer to buffer
|
|
||||||
* @param size buffer size
|
|
||||||
*
|
|
||||||
* @return items copied in buffer, 0 if channel closed
|
|
||||||
*/
|
|
||||||
size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size);
|
|
||||||
|
|
||||||
/** Recieve data from VCP with timeout Waits till some data arrives during
|
|
||||||
* timeout
|
|
||||||
*
|
|
||||||
* @param buffer pointer to buffer
|
|
||||||
* @param size buffer size
|
|
||||||
* @param timeout rx timeout in ms
|
|
||||||
*
|
|
||||||
* @return items copied in buffer, 0 if channel closed or timeout occurs
|
|
||||||
*/
|
|
||||||
size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout);
|
|
||||||
|
|
||||||
/** Transmit data to VCP
|
|
||||||
*
|
|
||||||
* @param buffer pointer to buffer
|
|
||||||
* @param size buffer size
|
|
||||||
*/
|
|
||||||
void furi_hal_vcp_tx(const uint8_t* buffer, size_t size);
|
|
||||||
|
|
||||||
/** Check whether VCP is connected
|
|
||||||
*
|
|
||||||
* @return true if connected
|
|
||||||
*/
|
|
||||||
bool furi_hal_vcp_is_connected(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -177,7 +177,7 @@ static int32_t infrared_worker_rx_thread(void* thread_context) {
|
|||||||
notification_message(instance->notification, &sequence_blink_blue_10);
|
notification_message(instance->notification, &sequence_blink_blue_10);
|
||||||
}
|
}
|
||||||
if(instance->signal.timings_cnt == 0)
|
if(instance->signal.timings_cnt == 0)
|
||||||
notification_message(instance->notification, &sequence_display_on);
|
notification_message(instance->notification, &sequence_display_backlight_on);
|
||||||
while(sizeof(LevelDuration) ==
|
while(sizeof(LevelDuration) ==
|
||||||
xStreamBufferReceive(
|
xStreamBufferReceive(
|
||||||
instance->stream, &level_duration, sizeof(LevelDuration), 0)) {
|
instance->stream, &level_duration, sizeof(LevelDuration), 0)) {
|
||||||
|
|||||||
343
lib/subghz/protocols/firefly.c
Normal file
343
lib/subghz/protocols/firefly.c
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
#include "firefly.h"
|
||||||
|
|
||||||
|
#include "../blocks/const.h"
|
||||||
|
#include "../blocks/decoder.h"
|
||||||
|
#include "../blocks/encoder.h"
|
||||||
|
#include "../blocks/generic.h"
|
||||||
|
#include "../blocks/math.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Help
|
||||||
|
* https://phreakerclub.com/447
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TAG "SubGhzProtocolFirefly"
|
||||||
|
|
||||||
|
#define DIP_PATTERN "%c%c%c%c%c%c%c%c%c%c"
|
||||||
|
#define DATA_TO_DIP(dip) \
|
||||||
|
(dip & 0x0200 ? '1' : '0'), (dip & 0x0100 ? '1' : '0'), (dip & 0x0080 ? '1' : '0'), \
|
||||||
|
(dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), (dip & 0x0010 ? '1' : '0'), \
|
||||||
|
(dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), \
|
||||||
|
(dip & 0x0001 ? '1' : '0')
|
||||||
|
|
||||||
|
static const SubGhzBlockConst subghz_protocol_firefly_const = {
|
||||||
|
.te_short = 500,
|
||||||
|
.te_long = 1500,
|
||||||
|
.te_delta = 150,
|
||||||
|
.min_count_bit_for_found = 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubGhzProtocolDecoderFirefly {
|
||||||
|
SubGhzProtocolDecoderBase base;
|
||||||
|
|
||||||
|
SubGhzBlockDecoder decoder;
|
||||||
|
SubGhzBlockGeneric generic;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubGhzProtocolEncoderFirefly {
|
||||||
|
SubGhzProtocolEncoderBase base;
|
||||||
|
|
||||||
|
SubGhzProtocolBlockEncoder encoder;
|
||||||
|
SubGhzBlockGeneric generic;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FireflyDecoderStepReset = 0,
|
||||||
|
FireflyDecoderStepSaveDuration,
|
||||||
|
FireflyDecoderStepCheckDuration,
|
||||||
|
} FireflyDecoderStep;
|
||||||
|
|
||||||
|
const SubGhzProtocolDecoder subghz_protocol_firefly_decoder = {
|
||||||
|
.alloc = subghz_protocol_decoder_firefly_alloc,
|
||||||
|
.free = subghz_protocol_decoder_firefly_free,
|
||||||
|
|
||||||
|
.feed = subghz_protocol_decoder_firefly_feed,
|
||||||
|
.reset = subghz_protocol_decoder_firefly_reset,
|
||||||
|
|
||||||
|
.get_hash_data = subghz_protocol_decoder_firefly_get_hash_data,
|
||||||
|
.serialize = subghz_protocol_decoder_firefly_serialize,
|
||||||
|
.deserialize = subghz_protocol_decoder_firefly_deserialize,
|
||||||
|
.get_string = subghz_protocol_decoder_firefly_get_string,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGhzProtocolEncoder subghz_protocol_firefly_encoder = {
|
||||||
|
.alloc = subghz_protocol_encoder_firefly_alloc,
|
||||||
|
.free = subghz_protocol_encoder_firefly_free,
|
||||||
|
|
||||||
|
.deserialize = subghz_protocol_encoder_firefly_deserialize,
|
||||||
|
.stop = subghz_protocol_encoder_firefly_stop,
|
||||||
|
.yield = subghz_protocol_encoder_firefly_yield,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGhzProtocol subghz_protocol_firefly = {
|
||||||
|
.name = SUBGHZ_PROTOCOL_FIREFLY_NAME,
|
||||||
|
.type = SubGhzProtocolTypeStatic,
|
||||||
|
.flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable |
|
||||||
|
SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
|
||||||
|
|
||||||
|
.decoder = &subghz_protocol_firefly_decoder,
|
||||||
|
.encoder = &subghz_protocol_firefly_encoder,
|
||||||
|
};
|
||||||
|
|
||||||
|
void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment) {
|
||||||
|
SubGhzProtocolEncoderFirefly* instance = malloc(sizeof(SubGhzProtocolEncoderFirefly));
|
||||||
|
|
||||||
|
instance->base.protocol = &subghz_protocol_firefly;
|
||||||
|
instance->generic.protocol_name = instance->base.protocol->name;
|
||||||
|
|
||||||
|
instance->encoder.repeat = 10;
|
||||||
|
instance->encoder.size_upload = 28; //max 10bit*2 + 2 (start, stop)
|
||||||
|
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
|
||||||
|
instance->encoder.is_runing = false;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_encoder_firefly_free(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolEncoderFirefly* instance = context;
|
||||||
|
free(instance->encoder.upload);
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generating an upload from data.
|
||||||
|
* @param instance Pointer to a SubGhzProtocolEncoderFirefly instance
|
||||||
|
* @return true On success
|
||||||
|
*/
|
||||||
|
static bool subghz_protocol_encoder_firefly_get_upload(SubGhzProtocolEncoderFirefly* instance) {
|
||||||
|
furi_assert(instance);
|
||||||
|
size_t index = 0;
|
||||||
|
size_t size_upload = (instance->generic.data_count_bit * 2);
|
||||||
|
if(size_upload > instance->encoder.size_upload) {
|
||||||
|
FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer.");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
instance->encoder.size_upload = size_upload;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send key data
|
||||||
|
for(uint8_t i = instance->generic.data_count_bit; i > 1; i--) {
|
||||||
|
if(bit_read(instance->generic.data, i - 1)) {
|
||||||
|
//send bit 1
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short * 3);
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short);
|
||||||
|
} else {
|
||||||
|
//send bit 0
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short);
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Send end bit
|
||||||
|
if(bit_read(instance->generic.data, 0)) {
|
||||||
|
//send bit 1
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short * 3);
|
||||||
|
//Send PT_GUARD
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 42);
|
||||||
|
} else {
|
||||||
|
//send bit 0
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short);
|
||||||
|
//Send PT_GUARD
|
||||||
|
instance->encoder.upload[index++] =
|
||||||
|
level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 44);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolEncoderFirefly* instance = context;
|
||||||
|
bool res = false;
|
||||||
|
do {
|
||||||
|
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
|
||||||
|
FURI_LOG_E(TAG, "Deserialize error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//optional parameter parameter
|
||||||
|
flipper_format_read_uint32(
|
||||||
|
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
|
||||||
|
|
||||||
|
subghz_protocol_encoder_firefly_get_upload(instance);
|
||||||
|
instance->encoder.is_runing = true;
|
||||||
|
|
||||||
|
res = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_encoder_firefly_stop(void* context) {
|
||||||
|
SubGhzProtocolEncoderFirefly* instance = context;
|
||||||
|
instance->encoder.is_runing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelDuration subghz_protocol_encoder_firefly_yield(void* context) {
|
||||||
|
SubGhzProtocolEncoderFirefly* instance = context;
|
||||||
|
|
||||||
|
if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) {
|
||||||
|
instance->encoder.is_runing = false;
|
||||||
|
return level_duration_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||||
|
|
||||||
|
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||||
|
instance->encoder.repeat--;
|
||||||
|
instance->encoder.front = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* subghz_protocol_decoder_firefly_alloc(SubGhzEnvironment* environment) {
|
||||||
|
SubGhzProtocolDecoderFirefly* instance = malloc(sizeof(SubGhzProtocolDecoderFirefly));
|
||||||
|
instance->base.protocol = &subghz_protocol_firefly;
|
||||||
|
instance->generic.protocol_name = instance->base.protocol->name;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_decoder_firefly_free(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFirefly* instance = context;
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_decoder_firefly_reset(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFirefly* instance = context;
|
||||||
|
instance->decoder.parser_step = FireflyDecoderStepReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_decoder_firefly_feed(void* context, bool level, uint32_t duration) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFirefly* instance = context;
|
||||||
|
switch(instance->decoder.parser_step) {
|
||||||
|
case FireflyDecoderStepReset:
|
||||||
|
if((!level) && (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short * 42) <
|
||||||
|
subghz_protocol_firefly_const.te_delta * 20)) {
|
||||||
|
//Found header Firefly
|
||||||
|
instance->decoder.decode_data = 0;
|
||||||
|
instance->decoder.decode_count_bit = 0;
|
||||||
|
instance->decoder.parser_step = FireflyDecoderStepSaveDuration;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FireflyDecoderStepSaveDuration:
|
||||||
|
if(level) {
|
||||||
|
instance->decoder.te_last = duration;
|
||||||
|
instance->decoder.parser_step = FireflyDecoderStepCheckDuration;
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = FireflyDecoderStepReset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FireflyDecoderStepCheckDuration:
|
||||||
|
if(!level) { //save interval
|
||||||
|
if(duration >= (subghz_protocol_firefly_const.te_short * 5)) {
|
||||||
|
instance->decoder.parser_step = FireflyDecoderStepReset;
|
||||||
|
//checking that the duration matches the guardtime
|
||||||
|
if((DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short * 42) >
|
||||||
|
subghz_protocol_firefly_const.te_delta * 20)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(DURATION_DIFF(
|
||||||
|
instance->decoder.te_last, subghz_protocol_firefly_const.te_short) <
|
||||||
|
subghz_protocol_firefly_const.te_delta) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||||
|
} else if(
|
||||||
|
DURATION_DIFF(
|
||||||
|
instance->decoder.te_last, subghz_protocol_firefly_const.te_long) <
|
||||||
|
subghz_protocol_firefly_const.te_delta) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||||
|
}
|
||||||
|
if(instance->decoder.decode_count_bit ==
|
||||||
|
subghz_protocol_firefly_const.min_count_bit_for_found) {
|
||||||
|
instance->generic.serial = 0x0;
|
||||||
|
instance->generic.btn = 0x0;
|
||||||
|
|
||||||
|
instance->generic.data = instance->decoder.decode_data;
|
||||||
|
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
|
||||||
|
|
||||||
|
if(instance->base.callback)
|
||||||
|
instance->base.callback(&instance->base, instance->base.context);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_firefly_const.te_short) <
|
||||||
|
subghz_protocol_firefly_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, subghz_protocol_firefly_const.te_long) <
|
||||||
|
subghz_protocol_firefly_const.te_delta)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||||
|
instance->decoder.parser_step = FireflyDecoderStepSaveDuration;
|
||||||
|
} else if(
|
||||||
|
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_firefly_const.te_long) <
|
||||||
|
subghz_protocol_firefly_const.te_delta) &&
|
||||||
|
(DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short) <
|
||||||
|
subghz_protocol_firefly_const.te_delta)) {
|
||||||
|
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||||
|
instance->decoder.parser_step = FireflyDecoderStepSaveDuration;
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = FireflyDecoderStepReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
instance->decoder.parser_step = FireflyDecoderStepReset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_decoder_firefly_get_hash_data(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFirefly* instance = context;
|
||||||
|
return subghz_protocol_blocks_get_hash_data(
|
||||||
|
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_protocol_decoder_firefly_serialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format,
|
||||||
|
uint32_t frequency,
|
||||||
|
FuriHalSubGhzPreset preset) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFirefly* instance = context;
|
||||||
|
return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_protocol_decoder_firefly_deserialize(void* context, FlipperFormat* flipper_format) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFirefly* instance = context;
|
||||||
|
return subghz_block_generic_deserialize(&instance->generic, flipper_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_protocol_decoder_firefly_get_string(void* context, string_t output) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzProtocolDecoderFirefly* instance = context;
|
||||||
|
|
||||||
|
uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff;
|
||||||
|
|
||||||
|
uint64_t code_found_reverse = subghz_protocol_blocks_reverse_key(
|
||||||
|
instance->generic.data, instance->generic.data_count_bit);
|
||||||
|
|
||||||
|
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||||
|
|
||||||
|
string_cat_printf(
|
||||||
|
output,
|
||||||
|
"%s %dbit\r\n"
|
||||||
|
"Key:0x%08lX\r\n"
|
||||||
|
"Yek:0x%08lX\r\n"
|
||||||
|
"DIP:" DIP_PATTERN "\r\n",
|
||||||
|
instance->generic.protocol_name,
|
||||||
|
instance->generic.data_count_bit,
|
||||||
|
code_found_lo,
|
||||||
|
code_found_reverse_lo,
|
||||||
|
DATA_TO_DIP(code_found_lo));
|
||||||
|
}
|
||||||
109
lib/subghz/protocols/firefly.h
Normal file
109
lib/subghz/protocols/firefly.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
#define SUBGHZ_PROTOCOL_FIREFLY_NAME "Firefly"
|
||||||
|
|
||||||
|
typedef struct SubGhzProtocolDecoderFirefly SubGhzProtocolDecoderFirefly;
|
||||||
|
typedef struct SubGhzProtocolEncoderFirefly SubGhzProtocolEncoderFirefly;
|
||||||
|
|
||||||
|
extern const SubGhzProtocolDecoder subghz_protocol_firefly_decoder;
|
||||||
|
extern const SubGhzProtocolEncoder subghz_protocol_firefly_encoder;
|
||||||
|
extern const SubGhzProtocol subghz_protocol_firefly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate SubGhzProtocolEncoderFirefly.
|
||||||
|
* @param environment Pointer to a SubGhzEnvironment instance
|
||||||
|
* @return SubGhzProtocolEncoderFirefly* pointer to a SubGhzProtocolEncoderFirefly instance
|
||||||
|
*/
|
||||||
|
void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free SubGhzProtocolEncoderFirefly.
|
||||||
|
* @param context Pointer to a SubGhzProtocolEncoderFirefly instance
|
||||||
|
*/
|
||||||
|
void subghz_protocol_encoder_firefly_free(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize and generating an upload to send.
|
||||||
|
* @param context Pointer to a SubGhzProtocolEncoderFirefly instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @return true On success
|
||||||
|
*/
|
||||||
|
bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* flipper_format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forced transmission stop.
|
||||||
|
* @param context Pointer to a SubGhzProtocolEncoderFirefly instance
|
||||||
|
*/
|
||||||
|
void subghz_protocol_encoder_firefly_stop(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting the level and duration of the upload to be loaded into DMA.
|
||||||
|
* @param context Pointer to a SubGhzProtocolEncoderFirefly instance
|
||||||
|
* @return LevelDuration
|
||||||
|
*/
|
||||||
|
LevelDuration subghz_protocol_encoder_firefly_yield(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate SubGhzProtocolDecoderFirefly.
|
||||||
|
* @param environment Pointer to a SubGhzEnvironment instance
|
||||||
|
* @return SubGhzProtocolDecoderFirefly* pointer to a SubGhzProtocolDecoderFirefly instance
|
||||||
|
*/
|
||||||
|
void* subghz_protocol_decoder_firefly_alloc(SubGhzEnvironment* environment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free SubGhzProtocolDecoderFirefly.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFirefly instance
|
||||||
|
*/
|
||||||
|
void subghz_protocol_decoder_firefly_free(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset decoder SubGhzProtocolDecoderFirefly.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFirefly instance
|
||||||
|
*/
|
||||||
|
void subghz_protocol_decoder_firefly_reset(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a raw sequence of levels and durations received from the air.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFirefly instance
|
||||||
|
* @param level Signal level true-high false-low
|
||||||
|
* @param duration Duration of this level in, us
|
||||||
|
*/
|
||||||
|
void subghz_protocol_decoder_firefly_feed(void* context, bool level, uint32_t duration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting the hash sum of the last randomly received parcel.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFirefly instance
|
||||||
|
* @return hash Hash sum
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_decoder_firefly_get_hash_data(void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize data SubGhzProtocolDecoderFirefly.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFirefly instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @param frequency The frequency at which the signal was received, Hz
|
||||||
|
* @param preset The modulation on which the signal was received, FuriHalSubGhzPreset
|
||||||
|
* @return true On success
|
||||||
|
*/
|
||||||
|
bool subghz_protocol_decoder_firefly_serialize(
|
||||||
|
void* context,
|
||||||
|
FlipperFormat* flipper_format,
|
||||||
|
uint32_t frequency,
|
||||||
|
FuriHalSubGhzPreset preset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize data SubGhzProtocolDecoderFirefly.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFirefly instance
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @return true On success
|
||||||
|
*/
|
||||||
|
bool subghz_protocol_decoder_firefly_deserialize(void* context, FlipperFormat* flipper_format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting a textual representation of the received data.
|
||||||
|
* @param context Pointer to a SubGhzProtocolDecoderFirefly instance
|
||||||
|
* @param output Resulting text
|
||||||
|
*/
|
||||||
|
void subghz_protocol_decoder_firefly_get_string(void* context, string_t output);
|
||||||
@@ -7,7 +7,7 @@ const SubGhzProtocol* subghz_protocol_registry[] = {
|
|||||||
&subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia,
|
&subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia,
|
||||||
&subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis,
|
&subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis,
|
||||||
&subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_gate_tx,
|
&subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_gate_tx,
|
||||||
&subghz_protocol_raw,
|
&subghz_protocol_raw, &subghz_protocol_firefly,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "scher_khan.h"
|
#include "scher_khan.h"
|
||||||
#include "gate_tx.h"
|
#include "gate_tx.h"
|
||||||
#include "raw.h"
|
#include "raw.h"
|
||||||
|
#include "firefly.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registration by name SubGhzProtocol.
|
* Registration by name SubGhzProtocol.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo
|
|||||||
asm("nop");
|
asm("nop");
|
||||||
break;
|
break;
|
||||||
case U8X8_MSG_GPIO_RESET:
|
case U8X8_MSG_GPIO_RESET:
|
||||||
furi_hal_gpio_write(&gpio_display_rst, arg_int);
|
furi_hal_gpio_write(&gpio_display_rst_n, arg_int);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user