[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 <alleteam@gmail.com>
This commit is contained in:
parent
8b9210704a
commit
6f7bcdf9a7
@ -11,6 +11,8 @@ struct ViewHolder {
|
|||||||
|
|
||||||
BackCallback back_callback;
|
BackCallback back_callback;
|
||||||
void* back_context;
|
void* back_context;
|
||||||
|
|
||||||
|
uint8_t ongoing_input_events_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void view_holder_draw_callback(Canvas* canvas, void* context);
|
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) {
|
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);
|
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) {
|
static void view_holder_input_callback(InputEvent* event, void* context) {
|
||||||
ViewHolder* view_holder = 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;
|
bool is_consumed = false;
|
||||||
|
|
||||||
if(view_holder->view) {
|
if(view_holder->view) {
|
||||||
|
@ -35,11 +35,6 @@ void view_set_previous_callback(View* view, ViewNavigationCallback callback) {
|
|||||||
view->previous_callback = 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) {
|
void view_set_enter_callback(View* view, ViewCallback callback) {
|
||||||
furi_assert(view);
|
furi_assert(view);
|
||||||
view->enter_callback = callback;
|
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) {
|
void view_enter(View* view) {
|
||||||
furi_assert(view);
|
furi_assert(view);
|
||||||
if(view->enter_callback) view->enter_callback(view->context);
|
if(view->enter_callback) view->enter_callback(view->context);
|
||||||
|
@ -14,11 +14,6 @@ extern "C" {
|
|||||||
#define VIEW_NONE 0xFFFFFFFF
|
#define VIEW_NONE 0xFFFFFFFF
|
||||||
/* Ignore navigation event */
|
/* Ignore navigation event */
|
||||||
#define VIEW_IGNORE 0xFFFFFFFE
|
#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 {
|
typedef enum {
|
||||||
ViewOrientationHorizontal,
|
ViewOrientationHorizontal,
|
||||||
@ -119,12 +114,6 @@ void view_set_custom_callback(View* view, ViewCustomCallback callback);
|
|||||||
*/
|
*/
|
||||||
void view_set_previous_callback(View* view, ViewNavigationCallback 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
|
/* Set Enter callback
|
||||||
* @param view, pointer to View
|
* @param view, pointer to View
|
||||||
* @param callback, callback
|
* @param callback, callback
|
||||||
|
39
applications/gui/view_dispatcher.c
Executable file → Normal file
39
applications/gui/view_dispatcher.c
Executable file → Normal file
@ -91,6 +91,18 @@ void view_dispatcher_run(ViewDispatcher* view_dispatcher) {
|
|||||||
view_dispatcher_handle_custom_event(view_dispatcher, message.custom_event);
|
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) {
|
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) {
|
if(view_id == VIEW_NONE) {
|
||||||
view_dispatcher_set_current_view(view_dispatcher, NULL);
|
view_dispatcher_set_current_view(view_dispatcher, NULL);
|
||||||
} else if(view_id == VIEW_IGNORE) {
|
} else if(view_id == VIEW_IGNORE) {
|
||||||
} else if(view_id == VIEW_DESTROY) {
|
|
||||||
view_dispatcher_free(view_dispatcher);
|
|
||||||
} else {
|
} else {
|
||||||
View** view_pp = ViewDict_get(view_dispatcher->views, view_id);
|
View** view_pp = ViewDict_get(view_dispatcher->views, view_id);
|
||||||
furi_check(view_pp != NULL);
|
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) {
|
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;
|
bool is_consumed = false;
|
||||||
if(view_dispatcher->current_view) {
|
if(view_dispatcher->current_view) {
|
||||||
is_consumed = view_input(view_dispatcher->current_view, event);
|
is_consumed = view_input(view_dispatcher->current_view, event);
|
||||||
@ -219,13 +244,17 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(event->key == InputKeyOk) {
|
|
||||||
view_id = view_next(view_dispatcher->current_view);
|
|
||||||
}
|
}
|
||||||
if(!is_consumed) {
|
if(!is_consumed) {
|
||||||
view_dispatcher_switch_to_view(view_dispatcher, view_id);
|
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) {
|
void view_dispatcher_handle_tick_event(ViewDispatcher* view_dispatcher) {
|
||||||
|
@ -113,6 +113,7 @@ void view_dispatcher_remove_view(ViewDispatcher* view_dispatcher, uint32_t view_
|
|||||||
/** Switch to View
|
/** Switch to View
|
||||||
* @param view_dispatcher ViewDispatcher instance
|
* @param view_dispatcher ViewDispatcher instance
|
||||||
* @param view_id View id to register
|
* @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);
|
void view_dispatcher_switch_to_view(ViewDispatcher* view_dispatcher, uint32_t view_id);
|
||||||
|
|
||||||
|
@ -14,7 +14,12 @@ struct ViewDispatcher {
|
|||||||
Gui* gui;
|
Gui* gui;
|
||||||
ViewPort* view_port;
|
ViewPort* view_port;
|
||||||
ViewDict_t views;
|
ViewDict_t views;
|
||||||
|
|
||||||
View* current_view;
|
View* current_view;
|
||||||
|
|
||||||
|
View* delayed_next_view;
|
||||||
|
uint8_t ongoing_input_events_count;
|
||||||
|
|
||||||
ViewDispatcherCustomEventCallback custom_event_callback;
|
ViewDispatcherCustomEventCallback custom_event_callback;
|
||||||
ViewDispatcherNavigationEventCallback navigation_event_callback;
|
ViewDispatcherNavigationEventCallback navigation_event_callback;
|
||||||
ViewDispatcherTickEventCallback tick_event_callback;
|
ViewDispatcherTickEventCallback tick_event_callback;
|
||||||
|
@ -15,7 +15,6 @@ struct View {
|
|||||||
|
|
||||||
ViewModelType model_type;
|
ViewModelType model_type;
|
||||||
ViewNavigationCallback previous_callback;
|
ViewNavigationCallback previous_callback;
|
||||||
ViewNavigationCallback next_callback;
|
|
||||||
ViewCallback enter_callback;
|
ViewCallback enter_callback;
|
||||||
ViewCallback exit_callback;
|
ViewCallback exit_callback;
|
||||||
ViewOrientation orientation;
|
ViewOrientation orientation;
|
||||||
@ -42,9 +41,6 @@ bool view_custom(View* view, uint32_t event);
|
|||||||
/* Previous Callback for View dispatcher */
|
/* Previous Callback for View dispatcher */
|
||||||
uint32_t view_previous(View* view);
|
uint32_t view_previous(View* view);
|
||||||
|
|
||||||
/* Next Callback for View dispatcher */
|
|
||||||
uint32_t view_next(View* view);
|
|
||||||
|
|
||||||
/* Enter Callback for View dispatcher */
|
/* Enter Callback for View dispatcher */
|
||||||
void view_enter(View* view);
|
void view_enter(View* view);
|
||||||
|
|
||||||
|
@ -131,9 +131,6 @@ int32_t input_srv() {
|
|||||||
// Common state info
|
// Common state info
|
||||||
InputEvent event;
|
InputEvent event;
|
||||||
event.key = input->pin_states[i].pin->key;
|
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
|
// Short / Long / Repeat timer routine
|
||||||
if(state) {
|
if(state) {
|
||||||
@ -146,6 +143,10 @@ int32_t input_srv() {
|
|||||||
}
|
}
|
||||||
input->pin_states[i].press_counter = 0;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
ADD_SCENE(subghz, start, Start)
|
ADD_SCENE(subghz, start, Start)
|
||||||
ADD_SCENE(subghz, analyze, Analyze)
|
|
||||||
ADD_SCENE(subghz, receiver, Receiver)
|
ADD_SCENE(subghz, receiver, Receiver)
|
||||||
ADD_SCENE(subghz, save_name, SaveName)
|
ADD_SCENE(subghz, save_name, SaveName)
|
||||||
ADD_SCENE(subghz, save_success, SaveSuccess)
|
ADD_SCENE(subghz, save_success, SaveSuccess)
|
||||||
|
@ -25,8 +25,12 @@ const bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent e
|
|||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) {
|
if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) {
|
||||||
return scene_manager_search_and_switch_to_previous_scene(
|
if(!scene_manager_search_and_switch_to_previous_scene(
|
||||||
subghz->scene_manager, SubGhzSceneStart);
|
subghz->scene_manager, SubGhzSceneReceiver)) {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
subghz->scene_manager, SubGhzSceneStart);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "../subghz_i.h"
|
#include "../subghz_i.h"
|
||||||
|
|
||||||
enum SubmenuIndex {
|
enum SubmenuIndex {
|
||||||
SubmenuIndexAnalyze,
|
|
||||||
SubmenuIndexRead,
|
SubmenuIndexRead,
|
||||||
SubmenuIndexSaved,
|
SubmenuIndexSaved,
|
||||||
SubmenuIndexTest,
|
SubmenuIndexTest,
|
||||||
@ -18,12 +17,6 @@ const void subghz_scene_start_on_enter(void* context) {
|
|||||||
if(subghz->state_notifications == NOTIFICATION_STARTING_STATE) {
|
if(subghz->state_notifications == NOTIFICATION_STARTING_STATE) {
|
||||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||||
}
|
}
|
||||||
submenu_add_item(
|
|
||||||
subghz->submenu,
|
|
||||||
"Analyze",
|
|
||||||
SubmenuIndexAnalyze,
|
|
||||||
subghz_scene_start_submenu_callback,
|
|
||||||
subghz);
|
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz);
|
subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
@ -47,12 +40,7 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexAnalyze) {
|
if(event.event == SubmenuIndexRead) {
|
||||||
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) {
|
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
|
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
|
||||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
|
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
|
||||||
|
@ -70,13 +70,6 @@ SubGhz* subghz_alloc() {
|
|||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
subghz->view_dispatcher, SubGhzViewMenu, submenu_get_view(subghz->submenu));
|
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
|
// Receiver
|
||||||
subghz->subghz_receiver = subghz_receiver_alloc();
|
subghz->subghz_receiver = subghz_receiver_alloc();
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
@ -159,10 +152,6 @@ void subghz_free(SubGhz* subghz) {
|
|||||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewStatic);
|
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewStatic);
|
||||||
subghz_test_static_free(subghz->subghz_test_static);
|
subghz_test_static_free(subghz->subghz_test_static);
|
||||||
|
|
||||||
// Analyze
|
|
||||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewAnalyze);
|
|
||||||
subghz_analyze_free(subghz->subghz_analyze);
|
|
||||||
|
|
||||||
// Receiver
|
// Receiver
|
||||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewReceiver);
|
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewReceiver);
|
||||||
subghz_receiver_free(subghz->subghz_receiver);
|
subghz_receiver_free(subghz->subghz_receiver);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <m-string.h>
|
#include <m-string.h>
|
||||||
|
|
||||||
#define SUBGHZ_HISTORY_MAX 20
|
#define SUBGHZ_HISTORY_MAX 50
|
||||||
|
|
||||||
typedef struct SubGhzHistoryStruct SubGhzHistoryStruct;
|
typedef struct SubGhzHistoryStruct SubGhzHistoryStruct;
|
||||||
|
|
||||||
@ -88,7 +88,10 @@ SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, u
|
|||||||
instance->data.param1 = instance->history[idx].te;
|
instance->data.param1 = instance->history[idx].te;
|
||||||
return &instance->data;
|
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) {
|
void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx) {
|
||||||
if(instance->history[idx].code_count_bit < 33) {
|
if(instance->history[idx].code_count_bit < 33) {
|
||||||
string_printf(
|
string_printf(
|
||||||
|
@ -18,5 +18,6 @@ uint16_t subghz_history_get_item(SubGhzHistory* instance);
|
|||||||
uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx);
|
uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx);
|
||||||
const char* subghz_history_get_name(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_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);
|
void subghz_history_add_to_history(SubGhzHistory* instance, void* context);
|
||||||
SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
|
SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "subghz.h"
|
#include "subghz.h"
|
||||||
#include "views/subghz_analyze.h"
|
|
||||||
#include "views/subghz_receiver.h"
|
#include "views/subghz_receiver.h"
|
||||||
#include "views/subghz_transmitter.h"
|
#include "views/subghz_transmitter.h"
|
||||||
|
|
||||||
@ -59,7 +58,6 @@ struct SubGhz {
|
|||||||
char text_store[SUBGHZ_TEXT_STORE_SIZE + 1];
|
char text_store[SUBGHZ_TEXT_STORE_SIZE + 1];
|
||||||
uint8_t state_notifications;
|
uint8_t state_notifications;
|
||||||
|
|
||||||
SubghzAnalyze* subghz_analyze;
|
|
||||||
SubghzReceiver* subghz_receiver;
|
SubghzReceiver* subghz_receiver;
|
||||||
SubghzTransmitter* subghz_transmitter;
|
SubghzTransmitter* subghz_transmitter;
|
||||||
|
|
||||||
@ -71,7 +69,6 @@ struct SubGhz {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
SubGhzViewMenu,
|
SubGhzViewMenu,
|
||||||
|
|
||||||
SubGhzViewAnalyze,
|
|
||||||
SubGhzViewDialogEx,
|
SubGhzViewDialogEx,
|
||||||
SubGhzViewReceiver,
|
SubGhzViewReceiver,
|
||||||
SubGhzViewPopup,
|
SubGhzViewPopup,
|
||||||
|
@ -1,233 +0,0 @@
|
|||||||
#include "subghz_analyze.h"
|
|
||||||
#include "../subghz_i.h"
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <furi.h>
|
|
||||||
#include <furi-hal.h>
|
|
||||||
#include <input/input.h>
|
|
||||||
#include <gui/elements.h>
|
|
||||||
#include <notification/notification-messages.h>
|
|
||||||
|
|
||||||
#include <lib/subghz/subghz_worker.h>
|
|
||||||
#include <lib/subghz/protocols/subghz_protocol.h>
|
|
||||||
|
|
||||||
#include <assets_icons.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <gui/view.h>
|
|
||||||
|
|
||||||
typedef struct SubghzAnalyze SubghzAnalyze;
|
|
||||||
|
|
||||||
SubghzAnalyze* subghz_analyze_alloc();
|
|
||||||
|
|
||||||
void subghz_analyze_free(SubghzAnalyze* subghz_analyze);
|
|
||||||
|
|
||||||
View* subghz_analyze_get_view(SubghzAnalyze* subghz_analyze);
|
|
@ -14,8 +14,8 @@
|
|||||||
#define MAX_LEN_PX 100
|
#define MAX_LEN_PX 100
|
||||||
#define MENU_ITEMS 4
|
#define MENU_ITEMS 4
|
||||||
|
|
||||||
#define COUNT_FREQUNCY_SCANER 3
|
#define COUNT_FREQUNCY_HOPPER 3
|
||||||
const uint32_t subghz_frequencies_scanner[] = {
|
const uint32_t subghz_frequencies_hopper[] = {
|
||||||
/* 300 - 348 */
|
/* 300 - 348 */
|
||||||
315000000,
|
315000000,
|
||||||
/* 387 - 464 */
|
/* 387 - 464 */
|
||||||
@ -35,6 +35,7 @@ typedef enum {
|
|||||||
SubGhzHopperStateOFF,
|
SubGhzHopperStateOFF,
|
||||||
SubGhzHopperStatePause,
|
SubGhzHopperStatePause,
|
||||||
SubGhzHopperStateRunnig,
|
SubGhzHopperStateRunnig,
|
||||||
|
SubGhzHopperStateRSSITimeOut,
|
||||||
} SubGhzHopperState;
|
} SubGhzHopperState;
|
||||||
|
|
||||||
static const Icon* ReceiverItemIcons[] = {
|
static const Icon* ReceiverItemIcons[] = {
|
||||||
@ -51,6 +52,7 @@ struct SubghzReceiver {
|
|||||||
SubGhzProtocol* protocol;
|
SubGhzProtocol* protocol;
|
||||||
osTimerId timer;
|
osTimerId timer;
|
||||||
SubGhzHopperState hopper_state;
|
SubGhzHopperState hopper_state;
|
||||||
|
uint8_t hopper_timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -62,8 +64,6 @@ typedef struct {
|
|||||||
uint8_t temp_frequency;
|
uint8_t temp_frequency;
|
||||||
uint32_t real_frequency;
|
uint32_t real_frequency;
|
||||||
|
|
||||||
uint8_t tab_idx;
|
|
||||||
uint8_t menu_idx;
|
|
||||||
uint16_t idx;
|
uint16_t idx;
|
||||||
uint16_t list_offset;
|
uint16_t list_offset;
|
||||||
uint16_t history_item;
|
uint16_t history_item;
|
||||||
@ -146,6 +146,7 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
|
|||||||
bool scrollbar = model->history_item > 4;
|
bool scrollbar = model->history_item > 4;
|
||||||
string_t str_buff;
|
string_t str_buff;
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
|
uint32_t frequency;
|
||||||
string_init(str_buff);
|
string_init(str_buff);
|
||||||
|
|
||||||
canvas_clear(canvas);
|
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);
|
elements_scrollbar_pos(canvas, 126, 0, 49, model->idx, model->history_item);
|
||||||
}
|
}
|
||||||
canvas_set_color(canvas, ColorBlack);
|
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(
|
snprintf(
|
||||||
buffer,
|
buffer,
|
||||||
sizeof(buffer),
|
sizeof(buffer),
|
||||||
"%03ld.%03ld OOK",
|
"%03ld.%02ld",
|
||||||
model->real_frequency / 1000000 % 1000,
|
frequency / 1000000 % 1000,
|
||||||
model->real_frequency / 1000 % 1000);
|
frequency / 10000 % 100);
|
||||||
canvas_draw_str(canvas, 60, 61, buffer);
|
canvas_draw_str(canvas, 40, 62, buffer);
|
||||||
elements_button_left(canvas, "Config");
|
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;
|
break;
|
||||||
|
|
||||||
case ReceiverSceneStart:
|
case ReceiverSceneStart:
|
||||||
@ -194,15 +205,27 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
|
|||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
canvas_draw_str(canvas, 63, 40, "Scanning...");
|
canvas_draw_str(canvas, 63, 40, "Scanning...");
|
||||||
canvas_set_color(canvas, ColorBlack);
|
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(
|
snprintf(
|
||||||
buffer,
|
buffer,
|
||||||
sizeof(buffer),
|
sizeof(buffer),
|
||||||
"%03ld.%03ld OOK",
|
"%03ld.%02ld",
|
||||||
model->real_frequency / 1000000 % 1000,
|
frequency / 1000000 % 1000,
|
||||||
model->real_frequency / 1000 % 1000);
|
frequency / 10000 % 100);
|
||||||
canvas_draw_str(canvas, 60, 61, buffer);
|
canvas_draw_str(canvas, 40, 62, buffer);
|
||||||
elements_button_left(canvas, "Config");
|
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;
|
break;
|
||||||
|
|
||||||
case ReceiverSceneConfig:
|
case ReceiverSceneConfig:
|
||||||
@ -264,6 +287,14 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
|
|||||||
switch(scene) {
|
switch(scene) {
|
||||||
case ReceiverSceneMain:
|
case ReceiverSceneMain:
|
||||||
if(event->key == InputKeyBack) {
|
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;
|
return false;
|
||||||
} else if(event->key == InputKeyUp) {
|
} else if(event->key == InputKeyUp) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
@ -456,32 +487,41 @@ static void subghz_receiver_timer_callback(void* context) {
|
|||||||
SubghzReceiver* subghz_receiver = context;
|
SubghzReceiver* subghz_receiver = context;
|
||||||
|
|
||||||
switch(subghz_receiver->hopper_state) {
|
switch(subghz_receiver->hopper_state) {
|
||||||
case SubGhzHopperStateOFF:
|
case SubGhzHopperStatePause:
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
case SubGhzHopperStatePause:
|
case SubGhzHopperStateOFF:
|
||||||
osTimerStart(subghz_receiver->timer, 1024 / 10);
|
osTimerStop(subghz_receiver->timer);
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
case SubGhzHopperStateRSSITimeOut:
|
||||||
|
if(subghz_receiver->hopper_timeout != 0) {
|
||||||
|
subghz_receiver->hopper_timeout--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
float rssi = -127.0f;
|
float rssi = -127.0f;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||||
// See RSSI Calculation timings in CC1101 17.3 RSSI
|
if(subghz_receiver->hopper_state != SubGhzHopperStateRSSITimeOut) {
|
||||||
rssi = furi_hal_subghz_get_rssi();
|
// See RSSI Calculation timings in CC1101 17.3 RSSI
|
||||||
|
rssi = furi_hal_subghz_get_rssi();
|
||||||
|
|
||||||
// Stay if RSSI is high enough
|
// Stay if RSSI is high enough
|
||||||
if(rssi > -90.0f) {
|
if(rssi > -90.0f) {
|
||||||
osTimerStart(subghz_receiver->timer, 1024 / 4);
|
subghz_receiver->hopper_timeout = 10;
|
||||||
return false;
|
subghz_receiver->hopper_state = SubGhzHopperStateRSSITimeOut;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
osTimerStart(subghz_receiver->timer, 1024 / 10);
|
subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select next frequency
|
// Select next frequency
|
||||||
if(model->frequency < COUNT_FREQUNCY_SCANER - 1) {
|
if(model->frequency < COUNT_FREQUNCY_HOPPER - 1) {
|
||||||
model->frequency++;
|
model->frequency++;
|
||||||
} else {
|
} else {
|
||||||
model->frequency = 0;
|
model->frequency = 0;
|
||||||
@ -491,7 +531,7 @@ static void subghz_receiver_timer_callback(void* context) {
|
|||||||
subghz_rx_end(subghz_receiver->worker);
|
subghz_rx_end(subghz_receiver->worker);
|
||||||
subghz_protocol_reset(subghz_receiver->protocol);
|
subghz_protocol_reset(subghz_receiver->protocol);
|
||||||
model->real_frequency =
|
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;
|
return true;
|
||||||
});
|
});
|
||||||
@ -553,7 +593,7 @@ SubghzReceiver* subghz_receiver_alloc() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
subghz_receiver->timer =
|
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;
|
subghz_receiver->hopper_state = SubGhzHopperStateOFF;
|
||||||
return subghz_receiver;
|
return subghz_receiver;
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,6 @@
|
|||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <notification/notification-messages.h>
|
#include <notification/notification-messages.h>
|
||||||
|
|
||||||
//#include <assets_icons.h>
|
|
||||||
#include <gui/icon_i.h>
|
|
||||||
|
|
||||||
struct SubghzTransmitter {
|
struct SubghzTransmitter {
|
||||||
View* view;
|
View* view;
|
||||||
SubghzTransmitterCallback callback;
|
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 uint8_t string_width = canvas_string_width(canvas, str);
|
||||||
const Icon* icon = &I_ButtonCenter_7x7;
|
const Icon* icon = &I_ButtonCenter_7x7;
|
||||||
const uint8_t icon_offset = 3;
|
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 button_width = string_width + horizontal_offset * 2 + icon_width_with_offset;
|
||||||
|
|
||||||
const uint8_t x = (canvas_width(canvas) - button_width) / 2 + 40;
|
const uint8_t x = (canvas_width(canvas) - button_width) / 2 + 40;
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include <furi-hal-ibutton.h>
|
#include <furi-hal-ibutton.h>
|
||||||
#include <furi-hal-resources.h>
|
#include <furi-hal-resources.h>
|
||||||
|
|
||||||
|
#include <stm32wbxx_ll_tim.h>
|
||||||
|
|
||||||
#define LFRFID_READ_TIM htim1
|
#define LFRFID_READ_TIM htim1
|
||||||
#define LFRFID_READ_CHANNEL TIM_CHANNEL_1
|
#define LFRFID_READ_CHANNEL TIM_CHANNEL_1
|
||||||
#define LFRFID_EMULATE_TIM htim2
|
#define LFRFID_EMULATE_TIM htim2
|
||||||
@ -216,7 +218,11 @@ void furi_hal_rfid_tim_emulate_stop() {
|
|||||||
|
|
||||||
void furi_hal_rfid_tim_reset() {
|
void furi_hal_rfid_tim_reset() {
|
||||||
HAL_TIM_Base_DeInit(&LFRFID_READ_TIM);
|
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);
|
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) {
|
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;
|
uint32_t period = (uint32_t)((SystemCoreClock) / freq) - 1;
|
||||||
furi_hal_rfid_set_read_period(period);
|
furi_hal_rfid_set_read_period(period);
|
||||||
furi_hal_rfid_set_read_pulse(period * duty_cycle);
|
furi_hal_rfid_set_read_pulse(period * duty_cycle);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user