From 6f7bcdf9a713b4b2caf3520f3773d92d57a27c90 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Tue, 31 Aug 2021 00:05:09 +0400 Subject: [PATCH] [FL-1755, FL-1756] added LL_DeInit timers, removed Analyze scene, redesigned astomatic frequency change mechanism, updated subghz read scene interface (#677) * SubGhz: Fix Timer hopping * SubGhz: add display of received packages and their maximum number. redesigned interface, the maximum number of received packages increased to 50 * SubGhz: add clearing history on exit read scene, jump after saving the key into the history of received signals * SubGhz: Fix honoring the width of the icon for transmitter scene * RFID: Fix [FL-1755] freeze after key emulation * SubGhz: drop analyze scene and views * SubGhz: fix save scene * Input, GUI: new event delivery scheme that groups event for complementarity. * Gui: update View Dispatcher documentation * Gui: remove dead code, wait till all input events are delivered in ViewDispatcher in queue mode. * Gui: update comment in ViewDispatcher * FuriHal: fix incorrect clock disable invocation * FuriHal: proper include * SubGhz: properly reset history in receiver view * Gui: correct view switch order and non-complementary events discarding Co-authored-by: Aleksandr Kutuzov --- applications/dialogs/view_holder.c | 13 + applications/gui/view.c | 14 -- applications/gui/view.h | 11 - applications/gui/view_dispatcher.c | 39 ++- applications/gui/view_dispatcher.h | 1 + applications/gui/view_dispatcher_i.h | 5 + applications/gui/view_i.h | 4 - applications/input/input.c | 7 +- .../subghz/scenes/subghz_scene_analyze.c | 19 -- .../subghz/scenes/subghz_scene_config.h | 1 - .../subghz/scenes/subghz_scene_save_success.c | 8 +- .../subghz/scenes/subghz_scene_start.c | 14 +- applications/subghz/subghz.c | 11 - applications/subghz/subghz_history.c | 7 +- applications/subghz/subghz_history.h | 1 + applications/subghz/subghz_i.h | 3 - applications/subghz/views/subghz_analyze.c | 233 ------------------ applications/subghz/views/subghz_analyze.h | 11 - applications/subghz/views/subghz_receiver.c | 98 +++++--- .../subghz/views/subghz_transmitter.c | 5 +- firmware/targets/f6/furi-hal/furi-hal-rfid.c | 8 +- 21 files changed, 147 insertions(+), 366 deletions(-) mode change 100755 => 100644 applications/gui/view_dispatcher.c delete mode 100644 applications/subghz/scenes/subghz_scene_analyze.c delete mode 100644 applications/subghz/views/subghz_analyze.c delete mode 100644 applications/subghz/views/subghz_analyze.h diff --git a/applications/dialogs/view_holder.c b/applications/dialogs/view_holder.c index c4e116ec..34e36818 100644 --- a/applications/dialogs/view_holder.c +++ b/applications/dialogs/view_holder.c @@ -11,6 +11,8 @@ struct ViewHolder { BackCallback back_callback; void* back_context; + + uint8_t ongoing_input_events_count; }; static void view_holder_draw_callback(Canvas* canvas, void* context); @@ -92,6 +94,7 @@ void view_holder_start(ViewHolder* view_holder) { } void view_holder_stop(ViewHolder* view_holder) { + while(view_holder->ongoing_input_events_count > 0) osDelay(1); view_port_enabled_set(view_holder->view_port, false); } @@ -114,6 +117,16 @@ static void view_holder_draw_callback(Canvas* canvas, void* context) { static void view_holder_input_callback(InputEvent* event, void* context) { ViewHolder* view_holder = context; + + if(event->type == InputTypeRelease && view_holder->ongoing_input_events_count > 0) { + view_holder->ongoing_input_events_count--; + } else if(event->type == InputTypePress) { + view_holder->ongoing_input_events_count++; + } else if(view_holder->ongoing_input_events_count == 0) { + FURI_LOG_E("ViewHolder", "non-complementary input, discarding"); + return; + } + bool is_consumed = false; if(view_holder->view) { diff --git a/applications/gui/view.c b/applications/gui/view.c index a992e246..8dea6a43 100644 --- a/applications/gui/view.c +++ b/applications/gui/view.c @@ -35,11 +35,6 @@ void view_set_previous_callback(View* view, ViewNavigationCallback callback) { view->previous_callback = callback; } -void view_set_next_callback(View* view, ViewNavigationCallback callback) { - furi_assert(view); - view->next_callback = callback; -} - void view_set_enter_callback(View* view, ViewCallback callback) { furi_assert(view); view->enter_callback = callback; @@ -169,15 +164,6 @@ uint32_t view_previous(View* view) { } } -uint32_t view_next(View* view) { - furi_assert(view); - if(view->next_callback) { - return view->next_callback(view->context); - } else { - return VIEW_IGNORE; - } -} - void view_enter(View* view) { furi_assert(view); if(view->enter_callback) view->enter_callback(view->context); diff --git a/applications/gui/view.h b/applications/gui/view.h index 38127a7b..4cef59fa 100644 --- a/applications/gui/view.h +++ b/applications/gui/view.h @@ -14,11 +14,6 @@ extern "C" { #define VIEW_NONE 0xFFFFFFFF /* Ignore navigation event */ #define VIEW_IGNORE 0xFFFFFFFE -/* Deatch from gui, deallocate Views and ViewDispatcher - * BE SUPER CAREFUL, deallocation happens automatically on GUI thread - * You ARE NOT owning ViewDispatcher and Views instances - */ -#define VIEW_DESTROY 0xFFFFFFFA typedef enum { ViewOrientationHorizontal, @@ -119,12 +114,6 @@ void view_set_custom_callback(View* view, ViewCustomCallback callback); */ void view_set_previous_callback(View* view, ViewNavigationCallback callback); -/* Set Navigation Next callback - * @param view, pointer to View - * @param callback, input callback - */ -void view_set_next_callback(View* view, ViewNavigationCallback callback); - /* Set Enter callback * @param view, pointer to View * @param callback, callback diff --git a/applications/gui/view_dispatcher.c b/applications/gui/view_dispatcher.c old mode 100755 new mode 100644 index c86efff5..d063a38a --- a/applications/gui/view_dispatcher.c +++ b/applications/gui/view_dispatcher.c @@ -91,6 +91,18 @@ void view_dispatcher_run(ViewDispatcher* view_dispatcher) { view_dispatcher_handle_custom_event(view_dispatcher, message.custom_event); } } + + // Wait till all input events delivered + while(view_dispatcher->ongoing_input_events_count > 0) { + osMessageQueueGet(view_dispatcher->queue, &message, NULL, osWaitForever); + if(message.type == ViewDispatcherMessageTypeInput) { + if(message.input.type == InputTypePress) { + view_dispatcher->ongoing_input_events_count++; + } else if(message.input.type == InputTypeRelease) { + view_dispatcher->ongoing_input_events_count--; + } + } + } } void view_dispatcher_stop(ViewDispatcher* view_dispatcher) { @@ -153,12 +165,15 @@ void view_dispatcher_switch_to_view(ViewDispatcher* view_dispatcher, uint32_t vi if(view_id == VIEW_NONE) { view_dispatcher_set_current_view(view_dispatcher, NULL); } else if(view_id == VIEW_IGNORE) { - } else if(view_id == VIEW_DESTROY) { - view_dispatcher_free(view_dispatcher); } else { View** view_pp = ViewDict_get(view_dispatcher->views, view_id); furi_check(view_pp != NULL); - view_dispatcher_set_current_view(view_dispatcher, *view_pp); + if(view_dispatcher->ongoing_input_events_count > 0) { + view_dispatcher->delayed_next_view = *view_pp; + } else { + view_dispatcher->delayed_next_view = NULL; + view_dispatcher_set_current_view(view_dispatcher, *view_pp); + } } } @@ -202,6 +217,16 @@ void view_dispatcher_input_callback(InputEvent* event, void* context) { } void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* event) { + // Ongoing input events counting + if(event->type == InputTypeRelease && view_dispatcher->ongoing_input_events_count > 0) { + view_dispatcher->ongoing_input_events_count--; + } else if(event->type == InputTypePress) { + view_dispatcher->ongoing_input_events_count++; + } else if(view_dispatcher->ongoing_input_events_count == 0) { + FURI_LOG_E("ViewDispatcher", "non-complementary input, discarding"); + return; + } + bool is_consumed = false; if(view_dispatcher->current_view) { is_consumed = view_input(view_dispatcher->current_view, event); @@ -219,13 +244,17 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e return; } } - } else if(event->key == InputKeyOk) { - view_id = view_next(view_dispatcher->current_view); } if(!is_consumed) { view_dispatcher_switch_to_view(view_dispatcher, view_id); } } + + // Delayed view switch + if(view_dispatcher->delayed_next_view && view_dispatcher->ongoing_input_events_count == 0) { + view_dispatcher_set_current_view(view_dispatcher, view_dispatcher->delayed_next_view); + view_dispatcher->delayed_next_view = NULL; + } } void view_dispatcher_handle_tick_event(ViewDispatcher* view_dispatcher) { diff --git a/applications/gui/view_dispatcher.h b/applications/gui/view_dispatcher.h index fd8b874f..895c9b78 100755 --- a/applications/gui/view_dispatcher.h +++ b/applications/gui/view_dispatcher.h @@ -113,6 +113,7 @@ void view_dispatcher_remove_view(ViewDispatcher* view_dispatcher, uint32_t view_ /** Switch to View * @param view_dispatcher ViewDispatcher instance * @param view_id View id to register + * @warning switching may be delayed till input events complementarity reached */ void view_dispatcher_switch_to_view(ViewDispatcher* view_dispatcher, uint32_t view_id); diff --git a/applications/gui/view_dispatcher_i.h b/applications/gui/view_dispatcher_i.h index c921d994..86ee3257 100644 --- a/applications/gui/view_dispatcher_i.h +++ b/applications/gui/view_dispatcher_i.h @@ -14,7 +14,12 @@ struct ViewDispatcher { Gui* gui; ViewPort* view_port; ViewDict_t views; + View* current_view; + + View* delayed_next_view; + uint8_t ongoing_input_events_count; + ViewDispatcherCustomEventCallback custom_event_callback; ViewDispatcherNavigationEventCallback navigation_event_callback; ViewDispatcherTickEventCallback tick_event_callback; diff --git a/applications/gui/view_i.h b/applications/gui/view_i.h index 9f75f528..a03f3c4e 100644 --- a/applications/gui/view_i.h +++ b/applications/gui/view_i.h @@ -15,7 +15,6 @@ struct View { ViewModelType model_type; ViewNavigationCallback previous_callback; - ViewNavigationCallback next_callback; ViewCallback enter_callback; ViewCallback exit_callback; ViewOrientation orientation; @@ -42,9 +41,6 @@ bool view_custom(View* view, uint32_t event); /* Previous Callback for View dispatcher */ uint32_t view_previous(View* view); -/* Next Callback for View dispatcher */ -uint32_t view_next(View* view); - /* Enter Callback for View dispatcher */ void view_enter(View* view); diff --git a/applications/input/input.c b/applications/input/input.c index 32a35597..6426ba20 100644 --- a/applications/input/input.c +++ b/applications/input/input.c @@ -131,9 +131,6 @@ int32_t input_srv() { // Common state info InputEvent event; event.key = input->pin_states[i].pin->key; - event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease; - // Send Press/Release event - notify_pubsub(&input->event_pubsub, &event); // Short / Long / Repeat timer routine if(state) { @@ -146,6 +143,10 @@ int32_t input_srv() { } input->pin_states[i].press_counter = 0; } + + // Send Press/Release event + event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease; + notify_pubsub(&input->event_pubsub, &event); } } diff --git a/applications/subghz/scenes/subghz_scene_analyze.c b/applications/subghz/scenes/subghz_scene_analyze.c deleted file mode 100644 index 33a891f2..00000000 --- a/applications/subghz/scenes/subghz_scene_analyze.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "../subghz_i.h" - -const void subghz_scene_analyze_on_enter(void* context) { - SubGhz* subghz = context; - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewAnalyze); -} - -const bool subghz_scene_analyze_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - if(event.type == SceneManagerEventTypeTick) { - notification_message(subghz->notifications, &sequence_blink_blue_10); - return true; - } - return false; -} - -const void subghz_scene_analyze_on_exit(void* context) { - // SubGhz* subghz = context; -} diff --git a/applications/subghz/scenes/subghz_scene_config.h b/applications/subghz/scenes/subghz_scene_config.h index 6686dde3..f11c95c3 100644 --- a/applications/subghz/scenes/subghz_scene_config.h +++ b/applications/subghz/scenes/subghz_scene_config.h @@ -1,5 +1,4 @@ ADD_SCENE(subghz, start, Start) -ADD_SCENE(subghz, analyze, Analyze) ADD_SCENE(subghz, receiver, Receiver) ADD_SCENE(subghz, save_name, SaveName) ADD_SCENE(subghz, save_success, SaveSuccess) diff --git a/applications/subghz/scenes/subghz_scene_save_success.c b/applications/subghz/scenes/subghz_scene_save_success.c index 4cbc9fcd..4d26ff54 100644 --- a/applications/subghz/scenes/subghz_scene_save_success.c +++ b/applications/subghz/scenes/subghz_scene_save_success.c @@ -25,8 +25,12 @@ const bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent e SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) { - return scene_manager_search_and_switch_to_previous_scene( - subghz->scene_manager, SubGhzSceneStart); + if(!scene_manager_search_and_switch_to_previous_scene( + subghz->scene_manager, SubGhzSceneReceiver)) { + scene_manager_search_and_switch_to_previous_scene( + subghz->scene_manager, SubGhzSceneStart); + } + return true; } } return false; diff --git a/applications/subghz/scenes/subghz_scene_start.c b/applications/subghz/scenes/subghz_scene_start.c index 2ddfca69..2baac87a 100644 --- a/applications/subghz/scenes/subghz_scene_start.c +++ b/applications/subghz/scenes/subghz_scene_start.c @@ -1,7 +1,6 @@ #include "../subghz_i.h" enum SubmenuIndex { - SubmenuIndexAnalyze, SubmenuIndexRead, SubmenuIndexSaved, SubmenuIndexTest, @@ -18,12 +17,6 @@ const void subghz_scene_start_on_enter(void* context) { if(subghz->state_notifications == NOTIFICATION_STARTING_STATE) { subghz->state_notifications = NOTIFICATION_IDLE_STATE; } - submenu_add_item( - subghz->submenu, - "Analyze", - SubmenuIndexAnalyze, - subghz_scene_start_submenu_callback, - subghz); submenu_add_item( subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz); submenu_add_item( @@ -47,12 +40,7 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexAnalyze) { - scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAnalyze); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneAnalyze); - return true; - } else if(event.event == SubmenuIndexRead) { + if(event.event == SubmenuIndexRead) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 23bab9a5..ab99bff2 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -70,13 +70,6 @@ SubGhz* subghz_alloc() { view_dispatcher_add_view( subghz->view_dispatcher, SubGhzViewMenu, submenu_get_view(subghz->submenu)); - // Analyze - subghz->subghz_analyze = subghz_analyze_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, - SubGhzViewAnalyze, - subghz_analyze_get_view(subghz->subghz_analyze)); - // Receiver subghz->subghz_receiver = subghz_receiver_alloc(); view_dispatcher_add_view( @@ -159,10 +152,6 @@ void subghz_free(SubGhz* subghz) { view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewStatic); subghz_test_static_free(subghz->subghz_test_static); - // Analyze - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewAnalyze); - subghz_analyze_free(subghz->subghz_analyze); - // Receiver view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewReceiver); subghz_receiver_free(subghz->subghz_receiver); diff --git a/applications/subghz/subghz_history.c b/applications/subghz/subghz_history.c index 1aacdea6..d5c4c894 100644 --- a/applications/subghz/subghz_history.c +++ b/applications/subghz/subghz_history.c @@ -6,7 +6,7 @@ #include #include -#define SUBGHZ_HISTORY_MAX 20 +#define SUBGHZ_HISTORY_MAX 50 typedef struct SubGhzHistoryStruct SubGhzHistoryStruct; @@ -88,7 +88,10 @@ SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, u instance->data.param1 = instance->history[idx].te; return &instance->data; } - +void subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output) { + furi_assert(instance); + string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX); +} void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx) { if(instance->history[idx].code_count_bit < 33) { string_printf( diff --git a/applications/subghz/subghz_history.h b/applications/subghz/subghz_history.h index a0964fa0..71e35cf9 100644 --- a/applications/subghz/subghz_history.h +++ b/applications/subghz/subghz_history.h @@ -18,5 +18,6 @@ uint16_t subghz_history_get_item(SubGhzHistory* instance); uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx); const char* subghz_history_get_name(SubGhzHistory* instance, uint16_t idx); void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx); +void subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output); void subghz_history_add_to_history(SubGhzHistory* instance, void* context); SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx); diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index f816503e..8d4ab93c 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -1,7 +1,6 @@ #pragma once #include "subghz.h" -#include "views/subghz_analyze.h" #include "views/subghz_receiver.h" #include "views/subghz_transmitter.h" @@ -59,7 +58,6 @@ struct SubGhz { char text_store[SUBGHZ_TEXT_STORE_SIZE + 1]; uint8_t state_notifications; - SubghzAnalyze* subghz_analyze; SubghzReceiver* subghz_receiver; SubghzTransmitter* subghz_transmitter; @@ -71,7 +69,6 @@ struct SubGhz { typedef enum { SubGhzViewMenu, - SubGhzViewAnalyze, SubGhzViewDialogEx, SubGhzViewReceiver, SubGhzViewPopup, diff --git a/applications/subghz/views/subghz_analyze.c b/applications/subghz/views/subghz_analyze.c deleted file mode 100644 index cef72303..00000000 --- a/applications/subghz/views/subghz_analyze.c +++ /dev/null @@ -1,233 +0,0 @@ -#include "subghz_analyze.h" -#include "../subghz_i.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -struct SubghzAnalyze { - View* view; - SubGhzWorker* worker; - SubGhzProtocol* protocol; -}; - -typedef struct { - uint8_t frequency; - uint32_t real_frequency; - uint32_t counter; - string_t text; - uint16_t scene; - SubGhzProtocolCommon parser; -} SubghzAnalyzeModel; - -static const char subghz_symbols[] = {'-', '\\', '|', '/'}; - -void subghz_analyze_draw(Canvas* canvas, SubghzAnalyzeModel* model) { - char buffer[64]; - - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - - snprintf( - buffer, - sizeof(buffer), - "Analyze: %03ld.%03ldMHz %c", - model->real_frequency / 1000000 % 1000, - model->real_frequency / 1000 % 1000, - subghz_symbols[model->counter % 4]); - canvas_draw_str(canvas, 0, 8, buffer); - - switch(model->scene) { - case 1: - canvas_draw_icon(canvas, 0, 10, &I_RFIDDolphinReceive_97x61); - canvas_invert_color(canvas); - canvas_draw_box(canvas, 80, 12, 20, 20); - canvas_invert_color(canvas); - canvas_draw_icon(canvas, 75, 18, &I_sub1_10px); - elements_multiline_text_aligned( - canvas, 90, 38, AlignCenter, AlignTop, "Detecting\r\nSubGhz"); - break; - - default: - canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 18, string_get_cstr(model->text)); - break; - } -} - -bool subghz_analyze_input(InputEvent* event, void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - - if(event->type != InputTypeShort) return false; - - if(event->key == InputKeyBack) { - return false; - } - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - bool model_updated = false; - - if(event->key == InputKeyLeft) { - if(model->frequency > 0) model->frequency--; - model_updated = true; - } else if(event->key == InputKeyRight) { - if(model->frequency < subghz_frequencies_count - 1) model->frequency++; - model_updated = true; - } - - if(model_updated) { - furi_hal_subghz_idle(); - model->real_frequency = - furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]); - furi_hal_subghz_rx(); - } - - return model_updated; - }); - - return true; -} - -void subghz_analyze_text_callback(string_t text, void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - model->counter++; - string_set(model->text, text); - model->scene = 0; - return true; - }); -} - -void subghz_analyze_protocol_callback(SubGhzProtocolCommon* parser, void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - char buffer[64]; - snprintf( - buffer, - sizeof(buffer), - "%s\r\n" - "K:%lX%lX\r\n" - "SN:%lX\r\n" - "BTN:%X", - parser->name, - (uint32_t)(parser->code_found >> 32), - (uint32_t)(parser->code_found & 0x00000000FFFFFFFF), - parser->serial, - parser->btn); - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - model->counter++; - model->parser = *parser; - string_set(model->text, buffer); - model->scene = 0; - return true; - }); -} - -void subghz_analyze_enter(void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - model->frequency = subghz_frequencies_433_92; - model->real_frequency = - furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]); - model->scene = 1; - return true; - }); - - hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); - - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, subghz_analyze->worker); - - subghz_worker_start(subghz_analyze->worker); - - furi_hal_subghz_flush_rx(); - furi_hal_subghz_rx(); -} - -void subghz_analyze_exit(void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - - subghz_worker_stop(subghz_analyze->worker); - - furi_hal_subghz_stop_async_rx(); - furi_hal_subghz_sleep(); -} - -SubghzAnalyze* subghz_analyze_alloc() { - SubghzAnalyze* subghz_analyze = furi_alloc(sizeof(SubghzAnalyze)); - - // View allocation and configuration - subghz_analyze->view = view_alloc(); - view_allocate_model(subghz_analyze->view, ViewModelTypeLocking, sizeof(SubghzAnalyzeModel)); - view_set_context(subghz_analyze->view, subghz_analyze); - view_set_draw_callback(subghz_analyze->view, (ViewDrawCallback)subghz_analyze_draw); - view_set_input_callback(subghz_analyze->view, subghz_analyze_input); - view_set_enter_callback(subghz_analyze->view, subghz_analyze_enter); - view_set_exit_callback(subghz_analyze->view, subghz_analyze_exit); - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - string_init(model->text); - return true; - }); - - subghz_analyze->worker = subghz_worker_alloc(); - subghz_analyze->protocol = subghz_protocol_alloc(); - - subghz_worker_set_overrun_callback( - subghz_analyze->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset); - subghz_worker_set_pair_callback( - subghz_analyze->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse); - subghz_worker_set_context(subghz_analyze->worker, subghz_analyze->protocol); - - subghz_protocol_load_keeloq_file( - subghz_analyze->protocol, "/ext/assets/subghz/keeloq_mfcodes"); - subghz_protocol_load_nice_flor_s_file( - subghz_analyze->protocol, "/ext/assets/subghz/nice_floor_s_rx"); - subghz_protocol_enable_dump_text( - subghz_analyze->protocol, subghz_analyze_text_callback, subghz_analyze); - - return subghz_analyze; -} - -void subghz_analyze_free(SubghzAnalyze* subghz_analyze) { - furi_assert(subghz_analyze); - - subghz_protocol_free(subghz_analyze->protocol); - subghz_worker_free(subghz_analyze->worker); - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - string_clear(model->text); - return true; - }); - view_free(subghz_analyze->view); - free(subghz_analyze); -} - -View* subghz_analyze_get_view(SubghzAnalyze* subghz_analyze) { - furi_assert(subghz_analyze); - return subghz_analyze->view; -} diff --git a/applications/subghz/views/subghz_analyze.h b/applications/subghz/views/subghz_analyze.h deleted file mode 100644 index b1a553e6..00000000 --- a/applications/subghz/views/subghz_analyze.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -typedef struct SubghzAnalyze SubghzAnalyze; - -SubghzAnalyze* subghz_analyze_alloc(); - -void subghz_analyze_free(SubghzAnalyze* subghz_analyze); - -View* subghz_analyze_get_view(SubghzAnalyze* subghz_analyze); diff --git a/applications/subghz/views/subghz_receiver.c b/applications/subghz/views/subghz_receiver.c index aa894deb..d08b1d0a 100644 --- a/applications/subghz/views/subghz_receiver.c +++ b/applications/subghz/views/subghz_receiver.c @@ -14,8 +14,8 @@ #define MAX_LEN_PX 100 #define MENU_ITEMS 4 -#define COUNT_FREQUNCY_SCANER 3 -const uint32_t subghz_frequencies_scanner[] = { +#define COUNT_FREQUNCY_HOPPER 3 +const uint32_t subghz_frequencies_hopper[] = { /* 300 - 348 */ 315000000, /* 387 - 464 */ @@ -35,6 +35,7 @@ typedef enum { SubGhzHopperStateOFF, SubGhzHopperStatePause, SubGhzHopperStateRunnig, + SubGhzHopperStateRSSITimeOut, } SubGhzHopperState; static const Icon* ReceiverItemIcons[] = { @@ -51,6 +52,7 @@ struct SubghzReceiver { SubGhzProtocol* protocol; osTimerId timer; SubGhzHopperState hopper_state; + uint8_t hopper_timeout; }; typedef struct { @@ -62,8 +64,6 @@ typedef struct { uint8_t temp_frequency; uint32_t real_frequency; - uint8_t tab_idx; - uint8_t menu_idx; uint16_t idx; uint16_t list_offset; uint16_t history_item; @@ -146,6 +146,7 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) { bool scrollbar = model->history_item > 4; string_t str_buff; char buffer[64]; + uint32_t frequency; string_init(str_buff); canvas_clear(canvas); @@ -174,15 +175,25 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) { elements_scrollbar_pos(canvas, 126, 0, 49, model->idx, model->history_item); } canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); + canvas_set_font(canvas, FontSecondary); + + elements_button_left(canvas, "Conf"); + if((model->real_frequency / 1000 % 10) > 4) { + frequency = model->real_frequency + 10000; + } else { + frequency = model->real_frequency; + } snprintf( buffer, sizeof(buffer), - "%03ld.%03ld OOK", - model->real_frequency / 1000000 % 1000, - model->real_frequency / 1000 % 1000); - canvas_draw_str(canvas, 60, 61, buffer); - elements_button_left(canvas, "Config"); + "%03ld.%02ld", + frequency / 1000000 % 1000, + frequency / 10000 % 100); + canvas_draw_str(canvas, 40, 62, buffer); + canvas_draw_str(canvas, 75, 62, "AM"); + subghz_history_get_text_space_left(model->history, str_buff); + canvas_draw_str(canvas, 94, 62, string_get_cstr(str_buff)); + canvas_draw_line(canvas, 38, 51, 125, 51); break; case ReceiverSceneStart: @@ -194,15 +205,27 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) { canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 63, 40, "Scanning..."); canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); + canvas_set_font(canvas, FontSecondary); + elements_button_left(canvas, "Conf"); + canvas_invert_color(canvas); + canvas_draw_box(canvas, 38, 52, 10, 10); + canvas_invert_color(canvas); + if((model->real_frequency / 1000 % 10) > 4) { + frequency = model->real_frequency + 10000; + } else { + frequency = model->real_frequency; + } snprintf( buffer, sizeof(buffer), - "%03ld.%03ld OOK", - model->real_frequency / 1000000 % 1000, - model->real_frequency / 1000 % 1000); - canvas_draw_str(canvas, 60, 61, buffer); - elements_button_left(canvas, "Config"); + "%03ld.%02ld", + frequency / 1000000 % 1000, + frequency / 10000 % 100); + canvas_draw_str(canvas, 40, 62, buffer); + canvas_draw_str(canvas, 75, 62, "AM"); + subghz_history_get_text_space_left(model->history, str_buff); + canvas_draw_str(canvas, 94, 62, string_get_cstr(str_buff)); + canvas_draw_line(canvas, 48, 51, 125, 51); break; case ReceiverSceneConfig: @@ -264,6 +287,14 @@ bool subghz_receiver_input(InputEvent* event, void* context) { switch(scene) { case ReceiverSceneMain: if(event->key == InputKeyBack) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + model->idx = 0; + model->list_offset = 0; + model->history_item = 0; + subghz_history_clean(model->history); + return true; + }); return false; } else if(event->key == InputKeyUp) { with_view_model( @@ -456,32 +487,41 @@ static void subghz_receiver_timer_callback(void* context) { SubghzReceiver* subghz_receiver = context; switch(subghz_receiver->hopper_state) { - case SubGhzHopperStateOFF: + case SubGhzHopperStatePause: return; break; - case SubGhzHopperStatePause: - osTimerStart(subghz_receiver->timer, 1024 / 10); + case SubGhzHopperStateOFF: + osTimerStop(subghz_receiver->timer); return; break; + case SubGhzHopperStateRSSITimeOut: + if(subghz_receiver->hopper_timeout != 0) { + subghz_receiver->hopper_timeout--; + return; + } + break; default: break; } float rssi = -127.0f; with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - // See RSSI Calculation timings in CC1101 17.3 RSSI - rssi = furi_hal_subghz_get_rssi(); + if(subghz_receiver->hopper_state != SubGhzHopperStateRSSITimeOut) { + // See RSSI Calculation timings in CC1101 17.3 RSSI + rssi = furi_hal_subghz_get_rssi(); - // Stay if RSSI is high enough - if(rssi > -90.0f) { - osTimerStart(subghz_receiver->timer, 1024 / 4); - return false; + // Stay if RSSI is high enough + if(rssi > -90.0f) { + subghz_receiver->hopper_timeout = 10; + subghz_receiver->hopper_state = SubGhzHopperStateRSSITimeOut; + return false; + } } else { - osTimerStart(subghz_receiver->timer, 1024 / 10); + subghz_receiver->hopper_state = SubGhzHopperStateRunnig; } // Select next frequency - if(model->frequency < COUNT_FREQUNCY_SCANER - 1) { + if(model->frequency < COUNT_FREQUNCY_HOPPER - 1) { model->frequency++; } else { model->frequency = 0; @@ -491,7 +531,7 @@ static void subghz_receiver_timer_callback(void* context) { subghz_rx_end(subghz_receiver->worker); subghz_protocol_reset(subghz_receiver->protocol); model->real_frequency = - subghz_rx(subghz_receiver->worker, subghz_frequencies_scanner[model->frequency]); + subghz_rx(subghz_receiver->worker, subghz_frequencies_hopper[model->frequency]); return true; }); @@ -553,7 +593,7 @@ SubghzReceiver* subghz_receiver_alloc() { }); subghz_receiver->timer = - osTimerNew(subghz_receiver_timer_callback, osTimerOnce, subghz_receiver, NULL); + osTimerNew(subghz_receiver_timer_callback, osTimerPeriodic, subghz_receiver, NULL); subghz_receiver->hopper_state = SubGhzHopperStateOFF; return subghz_receiver; } diff --git a/applications/subghz/views/subghz_transmitter.c b/applications/subghz/views/subghz_transmitter.c index efa35fde..814eae66 100644 --- a/applications/subghz/views/subghz_transmitter.c +++ b/applications/subghz/views/subghz_transmitter.c @@ -8,9 +8,6 @@ #include #include -//#include -#include - struct SubghzTransmitter { View* view; SubghzTransmitterCallback callback; @@ -64,7 +61,7 @@ static void subghz_transmitter_button_right(Canvas* canvas, const char* str) { const uint8_t string_width = canvas_string_width(canvas, str); const Icon* icon = &I_ButtonCenter_7x7; const uint8_t icon_offset = 3; - const uint8_t icon_width_with_offset = icon->width + icon_offset; + const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_offset; const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; const uint8_t x = (canvas_width(canvas) - button_width) / 2 + 40; diff --git a/firmware/targets/f6/furi-hal/furi-hal-rfid.c b/firmware/targets/f6/furi-hal/furi-hal-rfid.c index 514e5f34..4990c5a9 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-rfid.c +++ b/firmware/targets/f6/furi-hal/furi-hal-rfid.c @@ -2,6 +2,8 @@ #include #include +#include + #define LFRFID_READ_TIM htim1 #define LFRFID_READ_CHANNEL TIM_CHANNEL_1 #define LFRFID_EMULATE_TIM htim2 @@ -216,7 +218,11 @@ void furi_hal_rfid_tim_emulate_stop() { void furi_hal_rfid_tim_reset() { HAL_TIM_Base_DeInit(&LFRFID_READ_TIM); + LL_TIM_DeInit(TIM1); + LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_TIM1); HAL_TIM_Base_DeInit(&LFRFID_EMULATE_TIM); + LL_TIM_DeInit(TIM2); + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM2); } bool furi_hal_rfid_is_tim_emulate(TIM_HandleTypeDef* hw) { @@ -275,4 +281,4 @@ void furi_hal_rfid_change_read_config(float freq, float duty_cycle) { uint32_t period = (uint32_t)((SystemCoreClock) / freq) - 1; furi_hal_rfid_set_read_period(period); furi_hal_rfid_set_read_pulse(period * duty_cycle); -} \ No newline at end of file +}