diff --git a/applications/about/about.c b/applications/about/about.c index f785c2e4..6b4489f0 100644 --- a/applications/about/about.c +++ b/applications/about/about.c @@ -5,6 +5,7 @@ #include #include #include +#include #include typedef DialogMessageButton (*AboutDialogScreen)(DialogsApp* dialogs, DialogMessage* message); @@ -83,12 +84,13 @@ static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage* string_cat_printf( buffer, - "%d.F%dB%dC%d %s %s\n", + "%d.F%dB%dC%d %s:%s %s\n", furi_hal_version_get_hw_version(), furi_hal_version_get_hw_target(), furi_hal_version_get_hw_body(), furi_hal_version_get_hw_connect(), furi_hal_version_get_hw_region_name(), + furi_hal_region_get_name(), my_name ? my_name : "Unknown"); string_cat_printf(buffer, "Serial Number:\n"); diff --git a/applications/desktop/views/desktop_view_debug.c b/applications/desktop/views/desktop_view_debug.c index e2641193..69c82bdb 100644 --- a/applications/desktop/views/desktop_view_debug.c +++ b/applications/desktop/views/desktop_view_debug.c @@ -36,12 +36,13 @@ void desktop_debug_render(Canvas* canvas, void* model) { snprintf( buffer, sizeof(buffer), - "%d.F%dB%dC%d %s %s", + "%d.F%dB%dC%d %s:%s %s", furi_hal_version_get_hw_version(), furi_hal_version_get_hw_target(), furi_hal_version_get_hw_body(), furi_hal_version_get_hw_connect(), furi_hal_version_get_hw_region_name(), + furi_hal_region_get_name(), my_name ? my_name : "Unknown"); canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer); diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c index 3b4da647..60809e78 100644 --- a/applications/infrared/infrared.c +++ b/applications/infrared/infrared.c @@ -295,6 +295,13 @@ bool infrared_rename_current_remote(Infrared* infrared, const char* name) { } void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { + if(infrared->app_state.is_transmitting) { + FURI_LOG_D(INFRARED_LOG_TAG, "Transmitter is already active"); + return; + } else { + infrared->app_state.is_transmitting = true; + } + if(infrared_signal_is_raw(signal)) { InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size); @@ -304,8 +311,11 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { } DOLPHIN_DEED(DolphinDeedIrSend); - infrared_worker_tx_start(infrared->worker); infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend); + + infrared_worker_tx_set_get_signal_callback( + infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); + infrared_worker_tx_start(infrared->worker); } void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) { @@ -324,7 +334,16 @@ void infrared_tx_start_received(Infrared* infrared) { } void infrared_tx_stop(Infrared* infrared) { + if(!infrared->app_state.is_transmitting) { + FURI_LOG_D(INFRARED_LOG_TAG, "Transmitter is already stopped"); + return; + } else { + infrared->app_state.is_transmitting = false; + } + infrared_worker_tx_stop(infrared->worker); + infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL); + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); } diff --git a/applications/infrared/infrared_i.h b/applications/infrared/infrared_i.h index 4e9c79d5..95215258 100644 --- a/applications/infrared/infrared_i.h +++ b/applications/infrared/infrared_i.h @@ -43,6 +43,7 @@ #define INFRARED_APP_EXTENSION ".ir" #define INFRARED_DEFAULT_REMOTE_NAME "Remote" +#define INFRARED_LOG_TAG "InfraredApp" typedef enum { InfraredButtonIndexNone = -1, @@ -63,6 +64,7 @@ typedef enum { typedef struct { bool is_learning_new_remote; bool is_debug_enabled; + bool is_transmitting; InfraredEditTarget edit_target : 8; InfraredEditMode edit_mode : 8; int32_t current_button_index; diff --git a/applications/infrared/scenes/infrared_scene_learn_success.c b/applications/infrared/scenes/infrared_scene_learn_success.c index 49e2f45f..9368c849 100644 --- a/applications/infrared/scenes/infrared_scene_learn_success.c +++ b/applications/infrared/scenes/infrared_scene_learn_success.c @@ -2,11 +2,6 @@ #include -typedef enum { - InfraredSceneLearnSuccessStateIdle = 0, - InfraredSceneLearnSuccessStateSending = 1, -} InfraredSceneLearnSuccessState; - static void infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) { Infrared* infrared = context; @@ -21,9 +16,6 @@ void infrared_scene_learn_success_on_enter(void* context) { DOLPHIN_DEED(DolphinDeedIrLearnSuccess); infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn); - infrared_worker_tx_set_get_signal_callback( - infrared->worker, infrared_worker_tx_get_signal_steady_callback, context); - if(infrared_signal_is_raw(signal)) { InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter); @@ -63,57 +55,42 @@ void infrared_scene_learn_success_on_enter(void* context) { dialog_ex_set_context(dialog_ex, context); dialog_ex_enable_extended_events(dialog_ex); - scene_manager_set_scene_state( - infrared->scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx); } bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) { Infrared* infrared = context; SceneManager* scene_manager = infrared->scene_manager; - uint32_t scene_state = scene_manager_get_scene_state(scene_manager, InfraredSceneLearnSuccess); + const bool is_transmitter_idle = !infrared->app_state.is_transmitting; bool consumed = false; if(event.type == SceneManagerEventTypeTick) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { + if(is_transmitter_idle) { infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn); } consumed = true; } else if(event.type == SceneManagerEventTypeBack) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { + if(is_transmitter_idle) { scene_manager_next_scene(scene_manager, InfraredSceneAskBack); } consumed = true; } else if(event.type == SceneManagerEventTypeCustom) { if(event.event == DialogExResultLeft) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { + if(is_transmitter_idle) { scene_manager_next_scene(scene_manager, InfraredSceneAskRetry); } consumed = true; } else if(event.event == DialogExResultRight) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { + if(is_transmitter_idle) { scene_manager_next_scene(scene_manager, InfraredSceneLearnEnterName); } consumed = true; } else if(event.event == DialogExPressCenter) { - if(scene_state == InfraredSceneLearnSuccessStateIdle) { - scene_manager_set_scene_state( - scene_manager, - InfraredSceneLearnSuccess, - InfraredSceneLearnSuccessStateSending); - infrared_tx_start_received(infrared); - infrared_play_notification_message( - infrared, InfraredNotificationMessageBlinkStartSend); - } + infrared_tx_start_received(infrared); consumed = true; } else if(event.event == DialogExReleaseCenter) { - if(scene_state == InfraredSceneLearnSuccessStateSending) { - scene_manager_set_scene_state( - scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle); - infrared_tx_stop(infrared); - infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); - infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); - } + infrared_tx_stop(infrared); + infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); consumed = true; } } @@ -123,9 +100,5 @@ bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent even void infrared_scene_learn_success_on_exit(void* context) { Infrared* infrared = context; - InfraredWorker* worker = infrared->worker; dialog_ex_reset(infrared->dialog_ex); - infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); - infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); - infrared_worker_tx_set_get_signal_callback(worker, NULL, NULL); } diff --git a/applications/infrared/scenes/infrared_scene_remote.c b/applications/infrared/scenes/infrared_scene_remote.c index bcac5881..c1f5b662 100644 --- a/applications/infrared/scenes/infrared_scene_remote.c +++ b/applications/infrared/scenes/infrared_scene_remote.c @@ -31,9 +31,6 @@ void infrared_scene_remote_on_enter(void* context) { ButtonMenu* button_menu = infrared->button_menu; SceneManager* scene_manager = infrared->scene_manager; - infrared_worker_tx_set_get_signal_callback( - infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); - size_t button_count = infrared_remote_get_button_count(remote); for(size_t i = 0; i < button_count; ++i) { InfraredRemoteButton* button = infrared_remote_get_button(remote, i); @@ -73,12 +70,17 @@ void infrared_scene_remote_on_enter(void* context) { bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { Infrared* infrared = context; SceneManager* scene_manager = infrared->scene_manager; + const bool is_transmitter_idle = !infrared->app_state.is_transmitting; bool consumed = false; if(event.type == SceneManagerEventTypeBack) { - const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; - consumed = scene_manager_search_and_switch_to_previous_scene_one_of( - scene_manager, possible_scenes, COUNT_OF(possible_scenes)); + if(is_transmitter_idle) { + const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; + consumed = scene_manager_search_and_switch_to_previous_scene_one_of( + scene_manager, possible_scenes, COUNT_OF(possible_scenes)); + } else { + consumed = true; + } } else if(event.type == SceneManagerEventTypeCustom) { const uint16_t custom_type = infrared_custom_event_get_type(event.event); const int16_t button_index = infrared_custom_event_get_value(event.event); @@ -92,14 +94,19 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { consumed = true; } else if(custom_type == InfraredCustomEventTypeMenuSelected) { furi_assert(button_index < 0); - scene_manager_set_scene_state( - scene_manager, InfraredSceneRemote, (unsigned)button_index); - if(button_index == ButtonIndexPlus) { - infrared->app_state.is_learning_new_remote = false; - scene_manager_next_scene(scene_manager, InfraredSceneLearn); - consumed = true; - } else if(button_index == ButtonIndexEdit) { - scene_manager_next_scene(scene_manager, InfraredSceneEdit); + if(is_transmitter_idle) { + scene_manager_set_scene_state( + scene_manager, InfraredSceneRemote, (unsigned)button_index); + if(button_index == ButtonIndexPlus) { + infrared->app_state.is_learning_new_remote = false; + scene_manager_next_scene(scene_manager, InfraredSceneLearn); + consumed = true; + } else if(button_index == ButtonIndexEdit) { + scene_manager_next_scene(scene_manager, InfraredSceneEdit); + consumed = true; + } + + } else { consumed = true; } } @@ -110,7 +117,5 @@ bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { void infrared_scene_remote_on_exit(void* context) { Infrared* infrared = context; - infrared_tx_stop(infrared); - infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL); button_menu_reset(infrared->button_menu); } diff --git a/applications/infrared/scenes/infrared_scene_rpc.c b/applications/infrared/scenes/infrared_scene_rpc.c index cb5535fe..ca7bbd8d 100644 --- a/applications/infrared/scenes/infrared_scene_rpc.c +++ b/applications/infrared/scenes/infrared_scene_rpc.c @@ -44,8 +44,6 @@ bool infrared_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(arg && (state == InfraredRpcStateIdle)) { string_set_str(infrared->file_path, arg); result = infrared_remote_load(infrared->remote, infrared->file_path); - infrared_worker_tx_set_get_signal_callback( - infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); if(result) { scene_manager_set_scene_state( infrared->scene_manager, InfraredSceneRpc, InfraredRpcStateLoaded); diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.c b/firmware/targets/f7/furi_hal/furi_hal_clock.c index 09efe76d..a7c9b4d0 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_clock.c +++ b/firmware/targets/f7/furi_hal/furi_hal_clock.c @@ -75,7 +75,10 @@ void furi_hal_clock_init() { LL_EXTI_LINE_18); /* Why? Because that's why. See RM0434, Table 61. CPU1 vector table. */ LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_18); LL_RCC_EnableIT_LSECSS(); - LL_RCC_LSE_EnableCSS(); + /* ES0394, extended case of 2.2.2 */ + if(!LL_RCC_IsActiveFlag_BORRST()) { + LL_RCC_LSE_EnableCSS(); + } /* Main PLL configuration and activation */ LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_2, 8, LL_RCC_PLLR_DIV_2); diff --git a/firmware/targets/f7/furi_hal/furi_hal_version.c b/firmware/targets/f7/furi_hal/furi_hal_version.c index 7abee281..0d87c807 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_version.c +++ b/firmware/targets/f7/furi_hal/furi_hal_version.c @@ -262,6 +262,8 @@ const char* furi_hal_version_get_hw_region_name() { return "R02"; case FuriHalVersionRegionJp: return "R03"; + case FuriHalVersionRegionWorld: + return "R04"; } return "R??"; } diff --git a/firmware/targets/furi_hal_include/furi_hal_version.h b/firmware/targets/furi_hal_include/furi_hal_version.h index 500e0d81..720fdfd1 100644 --- a/firmware/targets/furi_hal_include/furi_hal_version.h +++ b/firmware/targets/furi_hal_include/furi_hal_version.h @@ -41,6 +41,7 @@ typedef enum { FuriHalVersionRegionEuRu = 0x01, FuriHalVersionRegionUsCaAu = 0x02, FuriHalVersionRegionJp = 0x03, + FuriHalVersionRegionWorld = 0x04, } FuriHalVersionRegion; /** Device Display */ diff --git a/scripts/toolchain/fbtenv.cmd b/scripts/toolchain/fbtenv.cmd index 471ce835..aac2a330 100644 --- a/scripts/toolchain/fbtenv.cmd +++ b/scripts/toolchain/fbtenv.cmd @@ -31,6 +31,7 @@ if not "%REAL_TOOLCHAIN_VERSION%" == "%FLIPPER_TOOLCHAIN_VERSION%" ( set "HOME=%USERPROFILE%" set "PYTHONHOME=%FBT_TOOLCHAIN_ROOT%\python" +set "PYTHONPATH=" set "PATH=%FBT_TOOLCHAIN_ROOT%\python;%FBT_TOOLCHAIN_ROOT%\bin;%FBT_TOOLCHAIN_ROOT%\protoc\bin;%FBT_TOOLCHAIN_ROOT%\openocd\bin;%PATH%" set "PROMPT=(fbt) %PROMPT%"