From f385340b2e9470026438ba1a345d29bf921989fe Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Fri, 10 Sep 2021 04:29:57 +0400 Subject: [PATCH] [FL-1758] SubGhz refactoring part 1 (#689) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGhz: refactoring * WeGet: Add support for outputting formatted lines, events center button pressed, center button released * Variable Item: slightly changed the display of data on the screen * SubGhz: add show errors, add show preset, refactoring * SubGhz: refactoring transmitter * SubGhz: removed unused modules * SubGhz: Add FuriHalSubGhzPresetOok270Async setting menu * SubGhz: fix annotation * SubGhz: add support Nero Radio Co-authored-by: あく --- applications/gui/modules/variable-item-list.c | 19 +- applications/gui/modules/variable-item-list.h | 3 + applications/gui/modules/widget.c | 14 + applications/gui/modules/widget.h | 17 + .../widget_elements/widget_element_button.c | 13 +- .../widget_elements/widget_element_i.h | 11 + .../widget_element_string_multi.c | 67 ++ .../subghz/scenes/subghz_scene_config.h | 4 +- .../subghz/scenes/subghz_scene_receiver.c | 143 +++- .../scenes/subghz_scene_receiver_config.c | 156 ++++ .../scenes/subghz_scene_receiver_info.c | 163 +++++ .../subghz/scenes/subghz_scene_save_name.c | 6 +- .../subghz/scenes/subghz_scene_set_type.c | 64 +- ...ene_no_man.c => subghz_scene_show_error.c} | 13 +- .../subghz/scenes/subghz_scene_transmitter.c | 86 ++- applications/subghz/subghz.c | 92 ++- applications/subghz/subghz_history.c | 13 +- applications/subghz/subghz_history.h | 12 +- applications/subghz/subghz_i.c | 131 +++- applications/subghz/subghz_i.h | 53 +- applications/subghz/views/subghz_receiver.c | 669 ++++-------------- applications/subghz/views/subghz_receiver.h | 30 +- .../subghz/views/subghz_transmitter.c | 116 +-- .../subghz/views/subghz_transmitter.h | 12 +- lib/subghz/protocols/subghz_protocol.c | 13 +- .../protocols/subghz_protocol_gate_tx.h | 2 +- lib/subghz/protocols/subghz_protocol_keeloq.c | 6 +- lib/subghz/protocols/subghz_protocol_keeloq.h | 2 +- .../protocols/subghz_protocol_nero_radio.c | 280 ++++++++ .../protocols/subghz_protocol_nero_radio.h | 72 ++ .../protocols/subghz_protocol_nero_sketch.h | 2 +- .../protocols/subghz_protocol_nice_flo.h | 2 +- .../protocols/subghz_protocol_princeton.c | 2 +- .../protocols/subghz_protocol_star_line.c | 6 +- 34 files changed, 1493 insertions(+), 801 deletions(-) create mode 100644 applications/gui/modules/widget_elements/widget_element_string_multi.c create mode 100644 applications/subghz/scenes/subghz_scene_receiver_config.c create mode 100644 applications/subghz/scenes/subghz_scene_receiver_info.c rename applications/subghz/scenes/{subghz_scene_no_man.c => subghz_scene_show_error.c} (72%) create mode 100644 lib/subghz/protocols/subghz_protocol_nero_radio.c create mode 100644 lib/subghz/protocols/subghz_protocol_nero_radio.h diff --git a/applications/gui/modules/variable-item-list.c b/applications/gui/modules/variable-item-list.c index 3ccac4ae..1879353f 100644 --- a/applications/gui/modules/variable-item-list.c +++ b/applications/gui/modules/variable-item-list.c @@ -68,10 +68,10 @@ static void variable_item_list_draw_callback(Canvas* canvas, void* _model) { canvas_draw_str(canvas, 73, item_text_y, "<"); } - canvas_draw_str(canvas, 84, item_text_y, string_get_cstr(item->current_value_text)); + canvas_draw_str(canvas, 80, item_text_y, string_get_cstr(item->current_value_text)); if(item->current_value_index < (item->values_count - 1)) { - canvas_draw_str(canvas, 113, item_text_y, ">"); + canvas_draw_str(canvas, 115, item_text_y, ">"); } } @@ -235,6 +235,21 @@ void variable_item_list_free(VariableItemList* variable_item_list) { free(variable_item_list); } +void variable_item_list_clean(VariableItemList* variable_item_list) { + furi_assert(variable_item_list); + + with_view_model( + variable_item_list->view, (VariableItemListModel * model) { + VariableItemArray_it_t it; + for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it); + VariableItemArray_next(it)) { + string_clean(VariableItemArray_ref(it)->current_value_text); + } + VariableItemArray_clean(model->items); + return false; + }); +} + View* variable_item_list_get_view(VariableItemList* variable_item_list) { furi_assert(variable_item_list); return variable_item_list->view; diff --git a/applications/gui/modules/variable-item-list.h b/applications/gui/modules/variable-item-list.h index ab64a74a..8844b419 100644 --- a/applications/gui/modules/variable-item-list.h +++ b/applications/gui/modules/variable-item-list.h @@ -18,6 +18,9 @@ VariableItemList* variable_item_list_alloc(); * @param variable_item_list VariableItemList instance */ void variable_item_list_free(VariableItemList* variable_item_list); + +void variable_item_list_clean(VariableItemList* variable_item_list); + View* variable_item_list_get_view(VariableItemList* variable_item_list); /** Add item to VariableItemList diff --git a/applications/gui/modules/widget.c b/applications/gui/modules/widget.c index 64a05605..4b561260 100755 --- a/applications/gui/modules/widget.c +++ b/applications/gui/modules/widget.c @@ -118,6 +118,20 @@ static void widget_add_element(Widget* widget, WidgetElement* element) { }); } +void widget_add_string_multi_element( + Widget* widget, + uint8_t x, + uint8_t y, + Align horizontal, + Align vertical, + Font font, + const char* text) { + furi_assert(widget); + WidgetElement* string_multi_element = + widget_element_string_multi_create(x, y, horizontal, vertical, font, text); + widget_add_element(widget, string_multi_element); +} + void widget_add_string_element( Widget* widget, uint8_t x, diff --git a/applications/gui/modules/widget.h b/applications/gui/modules/widget.h index 17c53dd9..943e63c4 100755 --- a/applications/gui/modules/widget.h +++ b/applications/gui/modules/widget.h @@ -26,6 +26,23 @@ void widget_clear(Widget* widget); */ View* widget_get_view(Widget* widget); +/** Add Multi String Element + * @param widget Widget instance + * @param x - x coordinate + * @param y - y coordinate + * @param horizontal - Align instance + * @param vertical - Align instance + * @param font Font instance + */ +void widget_add_string_multi_element( + Widget* widget, + uint8_t x, + uint8_t y, + Align horizontal, + Align vertical, + Font font, + const char* text); + /** Add String Element * @param widget Widget instance * @param x - x coordinate diff --git a/applications/gui/modules/widget_elements/widget_element_button.c b/applications/gui/modules/widget_elements/widget_element_button.c index c9eab8d1..4b8517e0 100644 --- a/applications/gui/modules/widget_elements/widget_element_button.c +++ b/applications/gui/modules/widget_elements/widget_element_button.c @@ -30,7 +30,18 @@ static bool gui_button_input(InputEvent* event, WidgetElement* element) { GuiButtonModel* model = element->model; bool consumed = false; - if((event->type == InputTypeShort) && model->callback) { + if(model->callback == NULL) return consumed; + + if(event->key == InputKeyOk && event->type == InputTypePress && + model->button_type == GuiButtonTypeCenter) { + model->callback(GuiButtonTypeCenterPress, model->context); + consumed = true; + } else if( + event->key == InputKeyOk && event->type == InputTypeRelease && + model->button_type == GuiButtonTypeCenter) { + model->callback(GuiButtonTypeCenterRelease, model->context); + consumed = true; + } else if(event->type == InputTypeShort) { if((model->button_type == GuiButtonTypeLeft) && (event->key == InputKeyLeft)) { model->callback(model->button_type, model->context); consumed = true; diff --git a/applications/gui/modules/widget_elements/widget_element_i.h b/applications/gui/modules/widget_elements/widget_element_i.h index d35325aa..d99e349f 100755 --- a/applications/gui/modules/widget_elements/widget_element_i.h +++ b/applications/gui/modules/widget_elements/widget_element_i.h @@ -6,6 +6,8 @@ typedef enum { GuiButtonTypeLeft, GuiButtonTypeCenter, GuiButtonTypeRight, + GuiButtonTypeCenterPress, + GuiButtonTypeCenterRelease, } GuiButtonType; typedef void (*ButtonCallback)(GuiButtonType result, void* context); @@ -28,6 +30,15 @@ struct WidgetElement { Widget* parent; }; +/* Create multi string element */ +WidgetElement* widget_element_string_multi_create( + uint8_t x, + uint8_t y, + Align horizontal, + Align vertical, + Font font, + const char* text); + /* Create string element */ WidgetElement* widget_element_string_create( uint8_t x, diff --git a/applications/gui/modules/widget_elements/widget_element_string_multi.c b/applications/gui/modules/widget_elements/widget_element_string_multi.c new file mode 100644 index 00000000..ad9c58f5 --- /dev/null +++ b/applications/gui/modules/widget_elements/widget_element_string_multi.c @@ -0,0 +1,67 @@ +#include "widget_element_i.h" +#include +#include + +typedef struct { + uint8_t x; + uint8_t y; + Align horizontal; + Align vertical; + Font font; + string_t text; +} GuiStringMultiModel; + +static void gui_string_multi_draw(Canvas* canvas, WidgetElement* element) { + furi_assert(canvas); + furi_assert(element); + GuiStringMultiModel* model = element->model; + + if(string_size(model->text)) { + canvas_set_font(canvas, model->font); + elements_multiline_text_aligned( + canvas, + model->x, + model->y, + model->horizontal, + model->vertical, + string_get_cstr(model->text)); + } +} + +static void gui_string_multi_free(WidgetElement* gui_string) { + furi_assert(gui_string); + + GuiStringMultiModel* model = gui_string->model; + string_clear(model->text); + free(gui_string->model); + free(gui_string); +} + +WidgetElement* widget_element_string_multi_create( + uint8_t x, + uint8_t y, + Align horizontal, + Align vertical, + Font font, + const char* text) { + furi_assert(text); + + // Allocate and init model + GuiStringMultiModel* model = furi_alloc(sizeof(GuiStringMultiModel)); + model->x = x; + model->y = y; + model->horizontal = horizontal; + model->vertical = vertical; + model->font = font; + string_init_set_str(model->text, text); + + // Allocate and init Element + WidgetElement* gui_string = furi_alloc(sizeof(WidgetElement)); + gui_string->parent = NULL; + gui_string->input = NULL; + gui_string->draw = gui_string_multi_draw; + gui_string->free = gui_string_multi_free; + gui_string->model = model; + + return gui_string; +} diff --git a/applications/subghz/scenes/subghz_scene_config.h b/applications/subghz/scenes/subghz_scene_config.h index 10ecd1c6..070097e7 100644 --- a/applications/subghz/scenes/subghz_scene_config.h +++ b/applications/subghz/scenes/subghz_scene_config.h @@ -1,10 +1,12 @@ ADD_SCENE(subghz, start, Start) ADD_SCENE(subghz, receiver, Receiver) +ADD_SCENE(subghz, receiver_config, ReceiverConfig) +ADD_SCENE(subghz, receiver_info, ReceiverInfo) ADD_SCENE(subghz, save_name, SaveName) ADD_SCENE(subghz, save_success, SaveSuccess) ADD_SCENE(subghz, saved, Saved) ADD_SCENE(subghz, transmitter, Transmitter) -ADD_SCENE(subghz, no_man, NoMan) +ADD_SCENE(subghz, show_error, ShowError) ADD_SCENE(subghz, test, Test) ADD_SCENE(subghz, test_static, TestStatic) ADD_SCENE(subghz, test_carrier, TestCarrier) diff --git a/applications/subghz/scenes/subghz_scene_receiver.c b/applications/subghz/scenes/subghz_scene_receiver.c index 3c9ba375..aa5eaabe 100644 --- a/applications/subghz/scenes/subghz_scene_receiver.c +++ b/applications/subghz/scenes/subghz_scene_receiver.c @@ -1,21 +1,102 @@ #include "../subghz_i.h" #include "../views/subghz_receiver.h" +static void subghz_scene_receiver_update_statusbar(void* context) { + SubGhz* subghz = context; + char frequency_str[20]; + char preset_str[10]; + string_t history_stat_str; + string_init(history_stat_str); + if(!subghz_history_get_text_space_left(subghz->txrx->history, history_stat_str)) { + snprintf( + frequency_str, + sizeof(frequency_str), + "%03ld.%02ld", + subghz->txrx->frequency / 1000000 % 1000, + subghz->txrx->frequency / 10000 % 100); + if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || + subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { + snprintf(preset_str, sizeof(preset_str), "AM"); + } else if(subghz->txrx->preset == FuriHalSubGhzPreset2FSKAsync) { + snprintf(preset_str, sizeof(preset_str), "FM"); + } else { + furi_check(0); + } + subghz_receiver_add_data_statusbar( + subghz->subghz_receiver, frequency_str, preset_str, string_get_cstr(history_stat_str)); + } else { + subghz_receiver_add_data_statusbar( + subghz->subghz_receiver, string_get_cstr(history_stat_str), "", ""); + subghz->state_notifications = NOTIFICATION_IDLE_STATE; + } + string_clear(history_stat_str); +} + void subghz_scene_receiver_callback(SubghzReceverEvent event, void* context) { furi_assert(context); SubGhz* subghz = context; view_dispatcher_send_custom_event(subghz->view_dispatcher, event); } +void subghz_scene_add_to_history_callback(SubGhzProtocolCommon* parser, void* context) { + furi_assert(context); + SubGhz* subghz = context; + string_t str_buff; + string_init(str_buff); + + if(subghz_history_add_to_history( + subghz->txrx->history, parser, subghz->txrx->frequency, subghz->txrx->preset)) { + subghz_protocol_reset(subghz->txrx->protocol); + string_clean(str_buff); + subghz_history_get_text_item_menu( + subghz->txrx->history, str_buff, subghz_history_get_item(subghz->txrx->history) - 1); + subghz_receiver_add_item_to_menu( + subghz->subghz_receiver, + string_get_cstr(str_buff), + subghz_history_get_type_protocol( + subghz->txrx->history, subghz_history_get_item(subghz->txrx->history) - 1)); + subghz_scene_receiver_update_statusbar(subghz); + } + string_clear(str_buff); +} + const void subghz_scene_receiver_on_enter(void* context) { SubGhz* subghz = context; - SubghzReceiver* subghz_receiver = subghz->subghz_receiver; - subghz_receiver_set_callback(subghz_receiver, subghz_scene_receiver_callback, subghz); + string_t str_buff; + string_init(str_buff); + + //Load history to receiver + subghz_receiver_exit(subghz->subghz_receiver); + for(uint8_t i = 0; i < subghz_history_get_item(subghz->txrx->history); i++) { + string_clean(str_buff); + subghz_history_get_text_item_menu(subghz->txrx->history, str_buff, i); + subghz_receiver_add_item_to_menu( + subghz->subghz_receiver, + string_get_cstr(str_buff), + subghz_history_get_type_protocol(subghz->txrx->history, i)); + } + string_clear(str_buff); + subghz_scene_receiver_update_statusbar(subghz); + subghz_receiver_set_callback(subghz->subghz_receiver, subghz_scene_receiver_callback, subghz); + subghz_protocol_enable_dump( + subghz->txrx->protocol, subghz_scene_add_to_history_callback, subghz); - subghz_receiver_set_protocol(subghz_receiver, subghz->protocol_result, subghz->protocol); - subghz_receiver_set_worker(subghz_receiver, subghz->worker); subghz->state_notifications = NOTIFICATION_RX_STATE; + if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { + subghz_rx_end(subghz->txrx->worker); + //subghz_sleep(); + subghz->txrx->txrx_state = SubGhzTxRxStateIdle; + }; + if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) { + subghz_begin(subghz->txrx->preset); + subghz_rx(subghz->txrx->worker, subghz->txrx->frequency); + subghz->txrx->txrx_state = SubGhzTxRxStateRx; + } + if(subghz->txrx->idx_menu_chosen != 0) { + subghz_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen); + } + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewReceiver); } @@ -24,51 +105,43 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - case SubghzReceverEventSave: - subghz->state_notifications = NOTIFICATION_IDLE_STATE; - subghz->frequency = subghz_receiver_get_frequency(subghz->subghz_receiver); - subghz->preset = subghz_receiver_get_preset(subghz->subghz_receiver); - subghz->protocol_result = subghz_receiver_get_protocol(subghz->subghz_receiver); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); - return true; - break; case SubghzReceverEventBack: - scene_manager_previous_scene(subghz->scene_manager); + // Stop CC1101 Rx + if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { + subghz_rx_end(subghz->txrx->worker); + subghz_sleep(); + subghz->txrx->txrx_state = SubGhzTxRxStateIdle; + }; + subghz_history_clean(subghz->txrx->history); + subghz->txrx->hopper_state = SubGhzHopperStateOFF; + subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; + subghz->txrx->preset = FuriHalSubGhzPresetOok650Async; + subghz->txrx->idx_menu_chosen = 0; + subghz_protocol_enable_dump(subghz->txrx->protocol, NULL, subghz); + scene_manager_search_and_switch_to_previous_scene( + subghz->scene_manager, SubGhzSceneStart); return true; break; - case SubghzReceverEventSendStart: - subghz->state_notifications = NOTIFICATION_TX_STATE; - subghz->frequency = subghz_receiver_get_frequency(subghz->subghz_receiver); - subghz->preset = subghz_receiver_get_preset(subghz->subghz_receiver); - subghz->protocol_result = subghz_receiver_get_protocol(subghz->subghz_receiver); - subghz_transmitter_tx_start(subghz); - return true; - break; - case SubghzReceverEventSendStop: - subghz->state_notifications = NOTIFICATION_IDLE_STATE; - subghz_transmitter_tx_stop(subghz); - return true; - break; - case SubghzReceverEventMain: - subghz->state_notifications = NOTIFICATION_RX_STATE; + case SubghzReceverEventOK: + subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo); return true; break; case SubghzReceverEventConfig: subghz->state_notifications = NOTIFICATION_IDLE_STATE; - return true; - break; - case SubghzReceverEventSendHistoryFull: - subghz->state_notifications = NOTIFICATION_IDLE_STATE; + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig); return true; break; default: break; } } else if(event.type == SceneManagerEventTypeTick) { + if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { + subghz_hopper_update(subghz->txrx); + subghz_scene_receiver_update_statusbar(subghz); + } + switch(subghz->state_notifications) { - case NOTIFICATION_TX_STATE: - notification_message(subghz->notifications, &sequence_blink_red_10); - break; case NOTIFICATION_RX_STATE: notification_message(subghz->notifications, &sequence_blink_blue_10); break; diff --git a/applications/subghz/scenes/subghz_scene_receiver_config.c b/applications/subghz/scenes/subghz_scene_receiver_config.c new file mode 100644 index 00000000..276fc4b9 --- /dev/null +++ b/applications/subghz/scenes/subghz_scene_receiver_config.c @@ -0,0 +1,156 @@ +#include "../subghz_i.h" + +#define PRESET_COUNT 3 +const char* const preset_text[PRESET_COUNT] = { + "AM270", + "AM650", + "FM", +}; +const uint32_t preset_value[PRESET_COUNT] = { + FuriHalSubGhzPresetOok270Async, /** OOK, bandwidth 270kHz, asynchronous */ + FuriHalSubGhzPresetOok650Async, /** OOK, bandwidth 650kHz, asynchronous */ + FuriHalSubGhzPreset2FSKAsync, /** FM, asynchronous */ +}; + +#define HOPPING_COUNT 2 +const char* const hopping_text[HOPPING_COUNT] = { + "OFF", + "ON", +}; +const uint32_t hopping_value[HOPPING_COUNT] = { + SubGhzHopperStateOFF, + SubGhzHopperStateRunnig, +}; + +uint8_t subghz_scene_receiver_config_uint32_value_index( + const uint32_t value, + const uint32_t values[], + uint8_t values_count) { + int64_t last_value = INT64_MIN; + uint8_t index = 0; + for(uint8_t i = 0; i < values_count; i++) { + if((value >= last_value) && (value <= values[i])) { + index = i; + break; + } + last_value = values[i]; + } + return index; +} + +uint8_t subghz_scene_receiver_config_hopper_value_index( + const uint32_t value, + const uint32_t values[], + uint8_t values_count, + void* context) { + furi_assert(context); + SubGhz* subghz = context; + + if(value == values[0]) { + return 0; + } else { + variable_item_set_current_value_text( + (VariableItem*)scene_manager_get_scene_state( + subghz->scene_manager, SubGhzSceneReceiverConfig), + " -----"); + return 1; + } +} + +static void subghz_scene_receiver_config_set_frequency(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + if(subghz->txrx->hopper_state == SubGhzHopperStateOFF) { + variable_item_set_current_value_text(item, subghz_frequencies_text[index]); + subghz->txrx->frequency = subghz_frequencies[index]; + } +} + +static void subghz_scene_receiver_config_set_preset(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, preset_text[index]); + subghz->txrx->preset = preset_value[index]; +} + +static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, hopping_text[index]); + if(hopping_value[index] == SubGhzHopperStateOFF) { + variable_item_set_current_value_text( + (VariableItem*)scene_manager_get_scene_state( + subghz->scene_manager, SubGhzSceneReceiverConfig), + subghz_frequencies_text[subghz_frequencies_433_92]); + subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; + } else { + variable_item_set_current_value_text( + (VariableItem*)scene_manager_get_scene_state( + subghz->scene_manager, SubGhzSceneReceiverConfig), + " -----"); + } + + subghz->txrx->hopper_state = hopping_value[index]; +} + +void subghz_scene_receiver_config_callback(SubghzReceverEvent event, void* context) { + furi_assert(context); + SubGhz* subghz = context; + view_dispatcher_send_custom_event(subghz->view_dispatcher, event); +} + +const void subghz_scene_receiver_config_on_enter(void* context) { + SubGhz* subghz = context; + VariableItem* item; + uint8_t value_index; + + item = variable_item_list_add( + subghz->variable_item_list, + "Frequency:", + subghz_frequencies_count, + subghz_scene_receiver_config_set_frequency, + subghz); + value_index = subghz_scene_receiver_config_uint32_value_index( + subghz->txrx->frequency, subghz_frequencies, subghz_frequencies_count); + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneReceiverConfig, (uint32_t)item); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, subghz_frequencies_text[value_index]); + + item = variable_item_list_add( + subghz->variable_item_list, + "Hopping:", + HOPPING_COUNT, + subghz_scene_receiver_config_set_hopping_runing, + subghz); + value_index = subghz_scene_receiver_config_hopper_value_index( + subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, hopping_text[value_index]); + + item = variable_item_list_add( + subghz->variable_item_list, + "Modulation:", + PRESET_COUNT, + subghz_scene_receiver_config_set_preset, + subghz); + value_index = subghz_scene_receiver_config_uint32_value_index( + subghz->txrx->preset, preset_value, PRESET_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, preset_text[value_index]); + + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewVariableItemList); +} + +const bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent event) { + //SubGhz* subghz = context; + return false; +} + +const void subghz_scene_receiver_config_on_exit(void* context) { + SubGhz* subghz = context; + variable_item_list_clean(subghz->variable_item_list); +} diff --git a/applications/subghz/scenes/subghz_scene_receiver_info.c b/applications/subghz/scenes/subghz_scene_receiver_info.c new file mode 100644 index 00000000..6d0d371e --- /dev/null +++ b/applications/subghz/scenes/subghz_scene_receiver_info.c @@ -0,0 +1,163 @@ +#include "../subghz_i.h" + +void subghz_scene_receiver_info_callback(GuiButtonType result, void* context) { + furi_assert(context); + SubGhz* subghz = context; + view_dispatcher_send_custom_event(subghz->view_dispatcher, result); +} + +static bool subghz_scene_receiver_info_update_parser(void* context) { + SubGhz* subghz = context; + subghz->txrx->protocol_result = subghz_protocol_get_by_name( + subghz->txrx->protocol, + subghz_history_get_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); + + if(subghz->txrx->protocol_result->to_load_protocol != NULL) { + subghz->txrx->protocol_result->to_load_protocol( + subghz->txrx->protocol_result, + subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); + subghz->txrx->frequency = + subghz_history_get_frequency(subghz->txrx->history, subghz->txrx->idx_menu_chosen); + subghz->txrx->preset = + subghz_history_get_preset(subghz->txrx->history, subghz->txrx->idx_menu_chosen); + return true; + } + return false; +} + +const void subghz_scene_receiver_info_on_enter(void* context) { + SubGhz* subghz = context; + + if(subghz_scene_receiver_info_update_parser(subghz)) { + char buffer_str[16]; + snprintf( + buffer_str, + sizeof(buffer_str), + "%03ld.%02ld", + subghz->txrx->frequency / 1000000 % 1000, + subghz->txrx->frequency / 10000 % 100); + widget_add_string_element( + subghz->widget, 78, 0, AlignLeft, AlignTop, FontSecondary, buffer_str); + if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || + subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { + snprintf(buffer_str, sizeof(buffer_str), "AM"); + } else if(subghz->txrx->preset == FuriHalSubGhzPreset2FSKAsync) { + snprintf(buffer_str, sizeof(buffer_str), "FM"); + } else { + furi_check(0); + } + widget_add_string_element( + subghz->widget, 113, 0, AlignLeft, AlignTop, FontSecondary, buffer_str); + string_t text; + string_init(text); + subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, text); + widget_add_string_multi_element( + subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(text)); + string_clear(text); + + if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_string && + strcmp(subghz->txrx->protocol_result->name, "KeeLoq")) { + widget_add_button_element( + subghz->widget, + GuiButtonTypeRight, + "Save", + subghz_scene_receiver_info_callback, + subghz); + widget_add_button_element( + subghz->widget, + GuiButtonTypeCenter, + "Send", + subghz_scene_receiver_info_callback, + subghz); + } + + } else { + widget_add_icon_element(subghz->widget, 32, 12, &I_DolphinFirstStart7_61x51); + widget_add_string_element( + subghz->widget, 13, 8, AlignLeft, AlignBottom, FontSecondary, "Error history parse."); + } + + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewWidget); +} + +const bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) { + SubGhz* subghz = context; + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeCenterPress) { + //CC1101 Stop RX -> Start TX + subghz->state_notifications = NOTIFICATION_TX_STATE; + if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { + subghz->txrx->hopper_state = SubGhzHopperStatePause; + } + if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { + subghz_rx_end(subghz->txrx->worker); + //subghz_sleep(); + subghz->txrx->txrx_state = SubGhzTxRxStateIdle; + } + if(!subghz_scene_receiver_info_update_parser(subghz)) { + return false; + } + if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) { + subghz_tx_start(subghz); + subghz->txrx->txrx_state = SubGhzTxRxStateTx; + } + return true; + } else if(event.event == GuiButtonTypeCenterRelease) { + //CC1101 Stop Tx -> Start RX + subghz->state_notifications = NOTIFICATION_IDLE_STATE; + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_tx_stop(subghz); + subghz->txrx->txrx_state = SubGhzTxRxStateIdle; + } + if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) { + subghz_begin(subghz->txrx->preset); + subghz_rx(subghz->txrx->worker, subghz->txrx->frequency); + subghz->txrx->txrx_state = SubGhzTxRxStateRx; + } + if(subghz->txrx->hopper_state == SubGhzHopperStatePause) { + subghz->txrx->hopper_state = SubGhzHopperStateRunnig; + } + subghz->state_notifications = NOTIFICATION_RX_STATE; + return true; + } else if(event.event == GuiButtonTypeRight) { + //CC1101 Stop RX -> Save + subghz->state_notifications = NOTIFICATION_IDLE_STATE; + if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { + subghz->txrx->hopper_state = SubGhzHopperStateOFF; + } + if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { + subghz_rx_end(subghz->txrx->worker); + subghz_sleep(); + subghz->txrx->txrx_state = SubGhzTxRxStateIdle; + } + if(!subghz_scene_receiver_info_update_parser(subghz)) { + return false; + } + if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->to_save_string && + strcmp(subghz->txrx->protocol_result->name, "KeeLoq")) { + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); + } + return true; + } + } else if(event.type == SceneManagerEventTypeTick) { + if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { + subghz_hopper_update(subghz->txrx); + } + switch(subghz->state_notifications) { + case NOTIFICATION_TX_STATE: + notification_message(subghz->notifications, &sequence_blink_red_10); + break; + case NOTIFICATION_RX_STATE: + notification_message(subghz->notifications, &sequence_blink_blue_10); + break; + default: + break; + } + } + return false; +} + +const void subghz_scene_receiver_info_on_exit(void* context) { + SubGhz* subghz = context; + widget_clear(subghz->widget); +} diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c index fba0c622..b73f31b9 100644 --- a/applications/subghz/scenes/subghz_scene_save_name.c +++ b/applications/subghz/scenes/subghz_scene_save_name.c @@ -35,11 +35,13 @@ const bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent even if(event.type == SceneManagerEventTypeCustom) { if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) { - if(subghz_save_protocol_to_file(subghz, subghz->text_store)) { + if(strcmp(subghz->text_store, "") && + subghz_save_protocol_to_file(subghz, subghz->text_store)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess); return true; } else { - //Error save + string_set(subghz->error_str, "No name file"); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); return true; } } diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/subghz/scenes/subghz_scene_set_type.c index d0981792..c506a5c7 100644 --- a/applications/subghz/scenes/subghz_scene_set_type.c +++ b/applications/subghz/scenes/subghz_scene_set_type.c @@ -8,15 +8,18 @@ enum SubmenuIndex { SubmenuIndexCAME12bit, SubmenuIndexCAME24bit, SubmenuIndexNeroSketch, + SubmenuIndexNeroRadio, SubmenuIndexGateTX, SubmenuIndexDoorHan, }; bool subghz_scene_set_type_submenu_to_find_protocol(void* context, const char* protocol_name) { SubGhz* subghz = context; - subghz->protocol_result = subghz_protocol_get_by_name(subghz->protocol, protocol_name); - if(subghz->protocol_result == NULL) { - //show error + subghz->txrx->protocol_result = + subghz_protocol_get_by_name(subghz->txrx->protocol, protocol_name); + if(subghz->txrx->protocol_result == NULL) { + string_set(subghz->error_str, "Protocol not found"); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); return false; } return true; @@ -62,6 +65,8 @@ const void subghz_scene_set_type_on_enter(void* context) { subghz); // submenu_add_item( // subghz->submenu, "Nero Sketch", SubmenuIndexNeroSketch, subghz_scene_set_type_submenu_callback, subghz); + // submenu_add_item( + // subghz->submenu, "Nero Radio", SubmenuIndexNeroRadio, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, "Gate TX_433", @@ -90,81 +95,86 @@ const bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event switch(event.event) { case SubmenuIndexPricenton: if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "Princeton")) { - subghz->protocol_result->code_last_count_bit = 24; + subghz->txrx->protocol_result->code_last_count_bit = 24; key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - subghz->protocol_result->code_last_found = key; + subghz->txrx->protocol_result->code_last_found = key; generated_protocol = true; } break; case SubmenuIndexNiceFlo12bit: if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "Nice FLO")) { - subghz->protocol_result->code_last_count_bit = 12; + subghz->txrx->protocol_result->code_last_count_bit = 12; key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4 - subghz->protocol_result->code_last_found = key; + subghz->txrx->protocol_result->code_last_found = key; generated_protocol = true; } break; case SubmenuIndexNiceFlo24bit: if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "Nice FLO")) { - subghz->protocol_result->code_last_count_bit = 24; + subghz->txrx->protocol_result->code_last_count_bit = 24; key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - subghz->protocol_result->code_last_found = key; + subghz->txrx->protocol_result->code_last_found = key; generated_protocol = true; } break; case SubmenuIndexCAME12bit: if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "CAME")) { - subghz->protocol_result->code_last_count_bit = 12; + subghz->txrx->protocol_result->code_last_count_bit = 12; key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4 - subghz->protocol_result->code_last_found = key; + subghz->txrx->protocol_result->code_last_found = key; generated_protocol = true; } break; case SubmenuIndexCAME24bit: if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "CAME")) { - subghz->protocol_result->code_last_count_bit = 24; + subghz->txrx->protocol_result->code_last_count_bit = 24; key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - subghz->protocol_result->code_last_found = key; + subghz->txrx->protocol_result->code_last_found = key; generated_protocol = true; } break; // case SubmenuIndexNeroSketch: // /* code */ // break; + // case SubmenuIndexNeroRadio: + // /* code */ + // break; case SubmenuIndexGateTX: if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "GateTX")) { - subghz->protocol_result->code_last_count_bit = 24; + subghz->txrx->protocol_result->code_last_count_bit = 24; key = (key & 0x00F0FFFF) | 0xF << 16; //btn 0xF, 0xC, 0xA, 0x6 - subghz->protocol_result->code_last_found = subghz_protocol_common_reverse_key( - key, subghz->protocol_result->code_last_count_bit); + subghz->txrx->protocol_result->code_last_found = + subghz_protocol_common_reverse_key( + key, subghz->txrx->protocol_result->code_last_count_bit); generated_protocol = true; } break; case SubmenuIndexDoorHan: if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "KeeLoq")) { - subghz->protocol_result->code_last_count_bit = 64; - subghz->protocol_result->serial = key & 0x0FFFFFFF; - subghz->protocol_result->btn = 0x2; //btn 0x1, 0x2, 0x4, 0x8 - subghz->protocol_result->cnt = 0x0003; + subghz->txrx->protocol_result->code_last_count_bit = 64; + subghz->txrx->protocol_result->serial = key & 0x0FFFFFFF; + subghz->txrx->protocol_result->btn = 0x2; //btn 0x1, 0x2, 0x4, 0x8 + subghz->txrx->protocol_result->cnt = 0x0003; if(subghz_protocol_keeloq_set_manufacture_name( - subghz->protocol_result, "DoorHan")) { - subghz->protocol_result->code_last_found = - subghz_protocol_keeloq_gen_key(subghz->protocol_result); + subghz->txrx->protocol_result, "DoorHan")) { + subghz->txrx->protocol_result->code_last_found = + subghz_protocol_keeloq_gen_key(subghz->txrx->protocol_result); generated_protocol = true; } else { generated_protocol = false; - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNoMan); + string_set(subghz->error_str, "No manufactory key"); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } } break; - default: return false; break; } + if(generated_protocol) { - subghz->frequency = subghz_frequencies[subghz_frequencies_433_92]; - subghz->preset = FuriHalSubGhzPresetOok650Async; + subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; + subghz->txrx->preset = FuriHalSubGhzPresetOok650Async; scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); return true; } diff --git a/applications/subghz/scenes/subghz_scene_no_man.c b/applications/subghz/scenes/subghz_scene_show_error.c similarity index 72% rename from applications/subghz/scenes/subghz_scene_no_man.c rename to applications/subghz/scenes/subghz_scene_show_error.c index d5f2e0de..08c487a7 100644 --- a/applications/subghz/scenes/subghz_scene_no_man.c +++ b/applications/subghz/scenes/subghz_scene_show_error.c @@ -2,26 +2,26 @@ #define SCENE_NO_MAN_CUSTOM_EVENT (11UL) -void subghz_scene_no_man_popup_callback(void* context) { +void subghz_scene_show_error_popup_callback(void* context) { SubGhz* subghz = context; view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_NO_MAN_CUSTOM_EVENT); } -const void subghz_scene_no_man_on_enter(void* context) { +const void subghz_scene_show_error_on_enter(void* context) { SubGhz* subghz = context; // Setup view Popup* popup = subghz->popup; popup_set_icon(popup, 32, 12, &I_DolphinFirstStart7_61x51); - popup_set_header(popup, "No manufactory key", 13, 8, AlignLeft, AlignBottom); + popup_set_header(popup, string_get_cstr(subghz->error_str), 64, 8, AlignCenter, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, subghz); - popup_set_callback(popup, subghz_scene_no_man_popup_callback); + popup_set_callback(popup, subghz_scene_show_error_popup_callback); popup_enable_timeout(popup); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewPopup); } -const bool subghz_scene_no_man_on_event(void* context, SceneManagerEvent event) { +const bool subghz_scene_show_error_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SCENE_NO_MAN_CUSTOM_EVENT) { @@ -33,7 +33,7 @@ const bool subghz_scene_no_man_on_event(void* context, SceneManagerEvent event) return false; } -const void subghz_scene_no_man_on_exit(void* context) { +const void subghz_scene_show_error_on_exit(void* context) { SubGhz* subghz = context; // Clear view @@ -45,4 +45,5 @@ const void subghz_scene_no_man_on_exit(void* context) { popup_set_context(popup, NULL); popup_set_timeout(popup, 0); popup_disable_timeout(popup); + string_clean(subghz->error_str); } diff --git a/applications/subghz/scenes/subghz_scene_transmitter.c b/applications/subghz/scenes/subghz_scene_transmitter.c index c363fff6..9628a094 100644 --- a/applications/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/subghz/scenes/subghz_scene_transmitter.c @@ -1,5 +1,6 @@ #include "../subghz_i.h" #include "../views/subghz_transmitter.h" +#include void subghz_scene_transmitter_callback(SubghzTransmitterEvent event, void* context) { furi_assert(context); @@ -7,42 +8,90 @@ void subghz_scene_transmitter_callback(SubghzTransmitterEvent event, void* conte view_dispatcher_send_custom_event(subghz->view_dispatcher, event); } +static void subghz_scene_transmitter_update_data_show(void* context) { + SubGhz* subghz = context; + + if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->get_upload_protocol) { + string_t key_str; + string_init(key_str); + char frequency_str[10]; + char preset_str[6]; + uint8_t show_button = 0; + subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, key_str); + + if((!strcmp(subghz->txrx->protocol_result->name, "KeeLoq")) && + (!strcmp( + subghz_protocol_keeloq_get_manufacture_name(subghz->txrx->protocol_result), + "Unknown"))) { + show_button = 0; + } else { + show_button = 1; + } + snprintf( + frequency_str, + sizeof(frequency_str), + "%03ld.%02ld", + subghz->txrx->frequency / 1000000 % 1000, + subghz->txrx->frequency / 10000 % 100); + if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || + subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { + snprintf(preset_str, sizeof(preset_str), "AM"); + } else if(subghz->txrx->preset == FuriHalSubGhzPreset2FSKAsync) { + snprintf(preset_str, sizeof(preset_str), "FM"); + } else { + furi_check(0); + } + + subghz_transmitter_add_data_to_show( + subghz->subghz_transmitter, + string_get_cstr(key_str), + frequency_str, + preset_str, + show_button); + string_clear(key_str); + } else { + string_set(subghz->error_str, "Protocol not found"); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); + } +} + const void subghz_scene_transmitter_on_enter(void* context) { SubGhz* subghz = context; - SubghzTransmitter* subghz_transmitter = subghz->subghz_transmitter; - - subghz_transmitter_set_callback(subghz_transmitter, subghz_scene_transmitter_callback, subghz); - subghz_transmitter_set_protocol(subghz_transmitter, subghz->protocol_result); - subghz_transmitter_set_frequency_preset(subghz_transmitter, subghz->frequency, subghz->preset); - - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTransmitter); - + subghz_transmitter_set_callback( + subghz->subghz_transmitter, subghz_scene_transmitter_callback, subghz); + subghz_scene_transmitter_update_data_show(subghz); subghz->state_notifications = NOTIFICATION_IDLE_STATE; + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTransmitter); } const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; - if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubghzTransmitterEventSendStart) { subghz->state_notifications = NOTIFICATION_TX_STATE; - subghz_transmitter_tx_start(subghz); + if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { + subghz_rx_end(subghz->txrx->worker); + subghz->txrx->txrx_state = SubGhzTxRxStateIdle; + } + if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) { + subghz_tx_start(subghz); + subghz_scene_transmitter_update_data_show(subghz); + subghz->txrx->txrx_state = SubGhzTxRxStateTx; + } return true; } else if(event.event == SubghzTransmitterEventSendStop) { subghz->state_notifications = NOTIFICATION_IDLE_STATE; - subghz_transmitter_tx_stop(subghz); - subghz_sleep(); + if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + subghz_tx_stop(subghz); + subghz_sleep(); + subghz->txrx->txrx_state = SubGhzTxRxStateIdle; + } return true; } else if(event.event == SubghzTransmitterEventBack) { subghz->state_notifications = NOTIFICATION_IDLE_STATE; scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneStart); return true; - } else if(event.event == SubghzTransmitterEventNoMan) { - subghz->state_notifications = NOTIFICATION_IDLE_STATE; - scene_manager_search_and_switch_to_previous_scene( - subghz->scene_manager, SubGhzSceneNoMan); - return true; } } else if(event.type == SceneManagerEventTypeTick) { if(subghz->state_notifications == NOTIFICATION_TX_STATE) { @@ -55,7 +104,6 @@ const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent ev const void subghz_scene_transmitter_on_exit(void* context) { SubGhz* subghz = context; - SubghzTransmitter* subghz_transmitter = subghz->subghz_transmitter; - subghz_transmitter_set_callback(subghz_transmitter, NULL, subghz); + subghz->state_notifications = NOTIFICATION_IDLE_STATE; } diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 865ec8df..5b356ab1 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -1,5 +1,22 @@ #include "subghz_i.h" +const char* const subghz_frequencies_text[] = { + "300.00", + "315.00", + "348.00", + "387.00", + "433.08", + "433.92", + "434.78", + "438.90", + "464.00", + "779.00", + "868.35", + "915.00", + "925.00", + "928.00", +}; + const uint32_t subghz_frequencies[] = { /* 300 - 348 */ 300000000, @@ -20,7 +37,15 @@ const uint32_t subghz_frequencies[] = { 928000000, }; +const uint32_t subghz_hopper_frequencies[] = { + 315000000, + 433920000, + 868350000, +}; + const uint32_t subghz_frequencies_count = sizeof(subghz_frequencies) / sizeof(uint32_t); +const uint32_t subghz_hopper_frequencies_count = + sizeof(subghz_hopper_frequencies) / sizeof(uint32_t); const uint32_t subghz_frequencies_433_92 = 5; bool subghz_custom_event_callback(void* context, uint32_t event) { @@ -77,11 +102,6 @@ SubGhz* subghz_alloc() { SubGhzViewReceiver, subghz_receiver_get_view(subghz->subghz_receiver)); - // Dialog - subghz->dialog_ex = dialog_ex_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, SubGhzViewDialogEx, dialog_ex_get_view(subghz->dialog_ex)); - // Popup subghz->popup = popup_alloc(); view_dispatcher_add_view( @@ -92,6 +112,11 @@ SubGhz* subghz_alloc() { view_dispatcher_add_view( subghz->view_dispatcher, SubGhzViewTextInput, text_input_get_view(subghz->text_input)); + // Custom Widget + subghz->widget = widget_alloc(); + view_dispatcher_add_view( + subghz->view_dispatcher, SubGhzViewWidget, widget_get_view(subghz->widget)); + // Transmitter subghz->subghz_transmitter = subghz_transmitter_alloc(); view_dispatcher_add_view( @@ -99,6 +124,13 @@ SubGhz* subghz_alloc() { SubGhzViewTransmitter, subghz_transmitter_get_view(subghz->subghz_transmitter)); + // Variable Item List + subghz->variable_item_list = variable_item_list_alloc(); + view_dispatcher_add_view( + subghz->view_dispatcher, + SubGhzViewVariableItemList, + variable_item_list_get_view(subghz->variable_item_list)); + // Carrier Test Module subghz->subghz_test_carrier = subghz_test_carrier_alloc(); view_dispatcher_add_view( @@ -120,17 +152,26 @@ SubGhz* subghz_alloc() { SubGhzViewStatic, subghz_test_static_get_view(subghz->subghz_test_static)); - //init Worker & Protocol - subghz->worker = subghz_worker_alloc(); - subghz->protocol = subghz_protocol_alloc(); + //init Worker & Protocol & History + subghz->txrx = furi_alloc(sizeof(SubGhzTxRx)); + subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; + subghz->txrx->preset = FuriHalSubGhzPresetOok650Async; + subghz->txrx->txrx_state = SubGhzTxRxStateIdle; + subghz->txrx->hopper_state = SubGhzHopperStateOFF; + subghz->txrx->history = subghz_history_alloc(); + subghz->txrx->worker = subghz_worker_alloc(); + subghz->txrx->protocol = subghz_protocol_alloc(); subghz_worker_set_overrun_callback( - subghz->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset); + subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset); subghz_worker_set_pair_callback( - subghz->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse); - subghz_worker_set_context(subghz->worker, subghz->protocol); + subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse); + subghz_worker_set_context(subghz->txrx->worker, subghz->txrx->protocol); - subghz_protocol_load_keeloq_file(subghz->protocol, "/ext/subghz/keeloq_mfcodes"); - subghz_protocol_load_nice_flor_s_file(subghz->protocol, "/ext/subghz/nice_floor_s_rx"); + //Init Error_str + string_init(subghz->error_str); + + subghz_protocol_load_keeloq_file(subghz->txrx->protocol, "/ext/subghz/keeloq_mfcodes"); + subghz_protocol_load_nice_flor_s_file(subghz->txrx->protocol, "/ext/subghz/nice_floor_s_rx"); //subghz_protocol_enable_dump_text(subghz->protocol, subghz_text_callback, subghz); @@ -160,18 +201,22 @@ void subghz_free(SubGhz* subghz) { view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTextInput); text_input_free(subghz->text_input); - // Receiver + // Custom Widget + view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewWidget); + widget_free(subghz->widget); + + // Transmitter view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTransmitter); subghz_transmitter_free(subghz->subghz_transmitter); + // Variable Item List + view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewVariableItemList); + variable_item_list_free(subghz->variable_item_list); + // Submenu view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewMenu); submenu_free(subghz->submenu); - // DialogEx - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewDialogEx); - dialog_ex_free(subghz->dialog_ex); - // Popup view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewPopup); popup_free(subghz->popup); @@ -186,9 +231,14 @@ void subghz_free(SubGhz* subghz) { furi_record_close("gui"); subghz->gui = NULL; - //Worker & Protocol - subghz_protocol_free(subghz->protocol); - subghz_worker_free(subghz->worker); + //Worker & Protocol & History + subghz_protocol_free(subghz->txrx->protocol); + subghz_worker_free(subghz->txrx->worker); + subghz_history_free(subghz->txrx->history); + free(subghz->txrx); + + //Error string + string_clear(subghz->error_str); // Notifications furi_record_close("notification"); diff --git a/applications/subghz/subghz_history.c b/applications/subghz/subghz_history.c index 16fac74b..b9fb90e7 100644 --- a/applications/subghz/subghz_history.c +++ b/applications/subghz/subghz_history.c @@ -128,21 +128,27 @@ void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, } } -void subghz_history_add_to_history(SubGhzHistory* instance, void* context) { +bool subghz_history_add_to_history( + SubGhzHistory* instance, + void* context, + uint32_t frequency, + FuriHalSubGhzPreset preset) { furi_assert(instance); furi_assert(context); SubGhzProtocolCommon* protocol = context; - if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return; + if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false; if((instance->code_last_found == (protocol->code_last_found & 0xFFFF0FFFFFFFFFFF)) && ((millis() - instance->last_update_timestamp) < 500)) { instance->last_update_timestamp = millis(); - return; + return false; } instance->code_last_found = protocol->code_last_found & 0xFFFF0FFFFFFFFFFF; instance->last_update_timestamp = millis(); + instance->history[instance->last_index_write].real_frequency = frequency; + instance->history[instance->last_index_write].preset = preset; instance->history[instance->last_index_write].te = 0; instance->history[instance->last_index_write].manufacture_name = NULL; instance->history[instance->last_index_write].name = protocol->name; @@ -161,4 +167,5 @@ void subghz_history_add_to_history(SubGhzHistory* instance, void* context) { instance->history[instance->last_index_write].type_protocol = protocol->type_protocol; instance->last_index_write++; + return true; } \ No newline at end of file diff --git a/applications/subghz/subghz_history.h b/applications/subghz/subghz_history.h index a1f7ee7f..406c1cee 100644 --- a/applications/subghz/subghz_history.h +++ b/applications/subghz/subghz_history.h @@ -1,3 +1,4 @@ + #pragma once #include @@ -94,8 +95,15 @@ bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output * * @param instance - SubGhzHistory instance * @param context - SubGhzProtocolCommon context + * @param frequency - frequency Hz + * @param preset - FuriHalSubGhzPreset preset + * @return bool; */ -void subghz_history_add_to_history(SubGhzHistory* instance, void* context); +bool subghz_history_add_to_history( + SubGhzHistory* instance, + void* context, + uint32_t frequency, + FuriHalSubGhzPreset preset); /** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data * @@ -104,3 +112,5 @@ void subghz_history_add_to_history(SubGhzHistory* instance, void* context); * @return SubGhzProtocolCommonLoad* */ SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx); + +void subghz_hopper_update(void* context); diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index a339edfb..cdac50c6 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -19,6 +19,9 @@ void subghz_begin(FuriHalSubGhzPreset preset) { uint32_t subghz_rx(void* context, uint32_t frequency) { furi_assert(context); + if(!furi_hal_subghz_is_frequency_valid(frequency)) { + furi_check(0); + } SubGhzWorker* worker = context; furi_hal_subghz_idle(); @@ -33,6 +36,9 @@ uint32_t subghz_rx(void* context, uint32_t frequency) { } uint32_t subghz_tx(uint32_t frequency) { + if(!furi_hal_subghz_is_frequency_valid(frequency)) { + furi_check(0); + } furi_hal_subghz_idle(); uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); @@ -53,6 +59,7 @@ void subghz_rx_end(void* context) { subghz_worker_stop(worker); furi_hal_subghz_stop_async_rx(); } + furi_hal_subghz_idle(); } void subghz_sleep(void) { @@ -66,41 +73,46 @@ void subghz_frequency_preset_to_str(void* context, string_t output) { output, "Frequency: %d\n" "Preset: %d\n", - (int)subghz->frequency, - (int)subghz->preset); + (int)subghz->txrx->frequency, + (int)subghz->txrx->preset); } -void subghz_transmitter_tx_start(void* context) { +void subghz_tx_start(void* context) { + furi_assert(context); SubGhz* subghz = context; - subghz->encoder = subghz_protocol_encoder_common_alloc(); - subghz->encoder->repeat = 200; //max repeat with the button held down + subghz->txrx->encoder = subghz_protocol_encoder_common_alloc(); + subghz->txrx->encoder->repeat = 200; //max repeat with the button held down //get upload - if(subghz->protocol_result->get_upload_protocol) { - if(subghz->protocol_result->get_upload_protocol(subghz->protocol_result, subghz->encoder)) { - if(subghz->preset) { - subghz_begin(subghz->preset); + if(subghz->txrx->protocol_result->get_upload_protocol) { + if(subghz->txrx->protocol_result->get_upload_protocol( + subghz->txrx->protocol_result, subghz->txrx->encoder)) { + if(subghz->txrx->preset) { + subghz_begin(subghz->txrx->preset); } else { - subghz_begin(FuriHalSubGhzPresetOok650Async); + subghz_begin(FuriHalSubGhzPresetOok270Async); } - if(subghz->frequency) { - subghz_tx(subghz->frequency); + if(subghz->txrx->frequency) { + subghz_tx(subghz->txrx->frequency); } else { subghz_tx(433920000); } //Start TX - furi_hal_subghz_start_async_tx(subghz_protocol_encoder_common_yield, subghz->encoder); + furi_hal_subghz_start_async_tx( + subghz_protocol_encoder_common_yield, subghz->txrx->encoder); } } } -void subghz_transmitter_tx_stop(void* context) { +void subghz_tx_stop(void* context) { + furi_assert(context); SubGhz* subghz = context; //Stop TX furi_hal_subghz_stop_async_tx(); - subghz_protocol_encoder_common_free(subghz->encoder); + subghz_protocol_encoder_common_free(subghz->txrx->encoder); + furi_hal_subghz_idle(); //if protocol dynamic then we save the last upload - if(subghz->protocol_result->type_protocol == TYPE_PROTOCOL_DYNAMIC) { + if(subghz->txrx->protocol_result->type_protocol == TYPE_PROTOCOL_DYNAMIC) { subghz_save_protocol_to_file(subghz, subghz->text_store); } notification_message(subghz->notifications, &sequence_reset_red); @@ -133,7 +145,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { if(res != 1) { break; } - subghz->frequency = (uint32_t)data; + subghz->txrx->frequency = (uint32_t)data; // Read and parse preset from 2st line if(!file_worker_read_until(file_worker, temp_str, '\n')) { @@ -143,7 +155,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { if(res != 1) { break; } - subghz->preset = (FuriHalSubGhzPreset)data; + subghz->txrx->preset = (FuriHalSubGhzPreset)data; // Read and parse name protocol from 2st line if(!file_worker_read_until(file_worker, temp_str, '\n')) { @@ -151,13 +163,13 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { } // strlen("Protocol: ") = 10 string_right(temp_str, 10); - subghz->protocol_result = - subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str)); - if(subghz->protocol_result == NULL) { + subghz->txrx->protocol_result = + subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str)); + if(subghz->txrx->protocol_result == NULL) { break; } - if(!subghz->protocol_result->to_load_protocol_from_file( - file_worker, subghz->protocol_result)) { + if(!subghz->txrx->protocol_result->to_load_protocol_from_file( + file_worker, subghz->txrx->protocol_result)) { break; } loaded = true; @@ -175,8 +187,9 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { } bool subghz_save_protocol_to_file(void* context, const char* dev_name) { + furi_assert(context); SubGhz* subghz = context; - furi_assert(subghz->protocol_result); + furi_assert(subghz->txrx->protocol_result); FileWorker* file_worker = file_worker_alloc(false); string_t dev_file_name; string_init(dev_file_name); @@ -210,7 +223,7 @@ bool subghz_save_protocol_to_file(void* context, const char* dev_name) { break; } //Get string save - subghz->protocol_result->to_save_string(subghz->protocol_result, temp_str); + subghz->txrx->protocol_result->to_save_string(subghz->txrx->protocol_result, temp_str); // Prepare and write data to file if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) { break; @@ -276,7 +289,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { if(sscanf_res != 1) { break; } - subghz->frequency = (uint32_t)data; + subghz->txrx->frequency = (uint32_t)data; // Read and parse preset from 2st line if(!file_worker_read_until(file_worker, temp_str, '\n')) { @@ -286,7 +299,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { if(sscanf_res != 1) { break; } - subghz->preset = (FuriHalSubGhzPreset)data; + subghz->txrx->preset = (FuriHalSubGhzPreset)data; // Read and parse name protocol from 3st line if(!file_worker_read_until(file_worker, temp_str, '\n')) { @@ -294,13 +307,13 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { } // strlen("Protocol: ") = 10 string_right(temp_str, 10); - subghz->protocol_result = - subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str)); - if(subghz->protocol_result == NULL) { + subghz->txrx->protocol_result = + subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str)); + if(subghz->txrx->protocol_result == NULL) { break; } - if(!subghz->protocol_result->to_load_protocol_from_file( - file_worker, subghz->protocol_result)) { + if(!subghz->txrx->protocol_result->to_load_protocol_from_file( + file_worker, subghz->txrx->protocol_result)) { break; } res = true; @@ -328,3 +341,57 @@ uint32_t subghz_random_serial(void) { } return (uint32_t)rand(); } + +void subghz_hopper_update(void* context) { + furi_assert(context); + SubGhzTxRx* txrx = context; + + switch(txrx->hopper_state) { + case SubGhzHopperStateOFF: + return; + break; + case SubGhzHopperStatePause: + return; + break; + case SubGhzHopperStateRSSITimeOut: + if(txrx->hopper_timeout != 0) { + txrx->hopper_timeout--; + return; + } + break; + default: + break; + } + float rssi = -127.0f; + if(txrx->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) { + txrx->hopper_timeout = 10; + txrx->hopper_state = SubGhzHopperStateRSSITimeOut; + return; + } + } else { + txrx->hopper_state = SubGhzHopperStateRunnig; + } + + // Select next frequency + if(txrx->hopper_idx_frequency < subghz_hopper_frequencies_count - 1) { + txrx->hopper_idx_frequency++; + } else { + txrx->hopper_idx_frequency = 0; + } + + if(txrx->txrx_state == SubGhzTxRxStateRx) { + subghz_rx_end(txrx->worker); + txrx->txrx_state = SubGhzTxRxStateIdle; + }; + if(txrx->txrx_state == SubGhzTxRxStateIdle) { + subghz_protocol_reset(txrx->protocol); + txrx->frequency = subghz_hopper_frequencies[txrx->hopper_idx_frequency]; + subghz_rx(txrx->worker, txrx->frequency); + txrx->txrx_state = SubGhzTxRxStateRx; + } +} diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index 8d4ab93c..9d088dc6 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -15,9 +15,9 @@ #include #include #include -#include #include #include +#include #include @@ -26,6 +26,8 @@ #include #include "subghz_history.h" +#include + #define SUBGHZ_TEXT_STORE_SIZE 128 #define NOTIFICATION_STARTING_STATE 0u @@ -33,48 +35,81 @@ #define NOTIFICATION_TX_STATE 2u #define NOTIFICATION_RX_STATE 3u +extern const char* const subghz_frequencies_text[]; extern const uint32_t subghz_frequencies[]; +extern const uint32_t subghz_hopper_frequencies[]; extern const uint32_t subghz_frequencies_count; +extern const uint32_t subghz_hopper_frequencies_count; extern const uint32_t subghz_frequencies_433_92; -struct SubGhz { - Gui* gui; - NotificationApp* notifications; +/** SubGhzTxRx state */ +typedef enum { + SubGhzTxRxStateIdle, + SubGhzTxRxStateRx, + SubGhzTxRxStateTx, +} SubGhzTxRxState; +/** SubGhzHopperState state */ +typedef enum { + SubGhzHopperStateOFF, + SubGhzHopperStateRunnig, + SubGhzHopperStatePause, + SubGhzHopperStateRSSITimeOut, +} SubGhzHopperState; + +struct SubGhzTxRx { SubGhzWorker* worker; SubGhzProtocol* protocol; SubGhzProtocolCommon* protocol_result; SubGhzProtocolCommonEncoder* encoder; uint32_t frequency; FuriHalSubGhzPreset preset; + SubGhzHistory* history; + uint16_t idx_menu_chosen; + SubGhzTxRxState txrx_state; + //bool hopper_runing; + SubGhzHopperState hopper_state; + uint8_t hopper_timeout; + uint8_t hopper_idx_frequency; +}; + +typedef struct SubGhzTxRx SubGhzTxRx; + +struct SubGhz { + Gui* gui; + NotificationApp* notifications; + + SubGhzTxRx* txrx; SceneManager* scene_manager; ViewDispatcher* view_dispatcher; Submenu* submenu; - DialogEx* dialog_ex; Popup* popup; TextInput* text_input; + Widget* widget; char text_store[SUBGHZ_TEXT_STORE_SIZE + 1]; uint8_t state_notifications; SubghzReceiver* subghz_receiver; SubghzTransmitter* subghz_transmitter; + VariableItemList* variable_item_list; SubghzTestStatic* subghz_test_static; SubghzTestCarrier* subghz_test_carrier; SubghzTestPacket* subghz_test_packet; + string_t error_str; }; typedef enum { SubGhzViewMenu, - SubGhzViewDialogEx, SubGhzViewReceiver, SubGhzViewPopup, SubGhzViewTextInput, + SubGhzViewWidget, SubGhzViewTransmitter, - + SubGhzViewVariableItemList, SubGhzViewStatic, SubGhzViewTestCarrier, SubGhzViewTestPacket, @@ -86,8 +121,8 @@ uint32_t subghz_tx(uint32_t frequency); void subghz_idle(void); void subghz_rx_end(void* context); void subghz_sleep(void); -void subghz_transmitter_tx_start(void* context); -void subghz_transmitter_tx_stop(void* context); +void subghz_tx_start(void* context); +void subghz_tx_stop(void* context); bool subghz_key_load(SubGhz* subghz, const char* file_path); bool subghz_save_protocol_to_file(void* context, const char* dev_name); bool subghz_load_protocol_from_file(SubGhz* subghz); diff --git a/applications/subghz/views/subghz_receiver.c b/applications/subghz/views/subghz_receiver.c index df70786b..4abf8225 100644 --- a/applications/subghz/views/subghz_receiver.c +++ b/applications/subghz/views/subghz_receiver.c @@ -1,42 +1,32 @@ #include "subghz_receiver.h" #include "../subghz_i.h" #include -#include -#include + #include #include -#include -#include - #include +#include +#include #define FRAME_HEIGHT 12 #define MAX_LEN_PX 100 #define MENU_ITEMS 4 -#define COUNT_FREQUNCY_HOPPER 3 -const uint32_t subghz_frequencies_hopper[] = { - /* 300 - 348 */ - 315000000, - /* 387 - 464 */ - 433920000, /* LPD433 mid */ - /* 779 - 928 */ - 868350000, +typedef struct { + string_t item_str; + uint8_t type; +} SubGhzReceiverMenuItem; + +ARRAY_DEF(SubGhzReceiverMenuItemArray, SubGhzReceiverMenuItem, M_POD_OPLIST) + +#define M_OPL_SubGhzReceiverMenuItemArray_t() \ + ARRAY_OPLIST(SubGhzReceiverMenuItemArray, M_POD_OPLIST) + +struct SubGhzReceiverHistory { + SubGhzReceiverMenuItemArray_t data; }; -typedef enum { - ReceiverSceneStart, - ReceiverSceneMain, - ReceiverSceneConfig, - ReceiverSceneInfo, -} SubghzReceiverScene; - -typedef enum { - SubGhzHopperStateOFF, - SubGhzHopperStatePause, - SubGhzHopperStateRunnig, - SubGhzHopperStateRSSITimeOut, -} SubGhzHopperState; +typedef struct SubGhzReceiverHistory SubGhzReceiverHistory; static const Icon* ReceiverItemIcons[] = { [TYPE_PROTOCOL_UNKNOWN] = &I_Quest_7x8, @@ -48,27 +38,16 @@ struct SubghzReceiver { View* view; SubghzReceiverCallback callback; void* context; - SubGhzWorker* worker; - SubGhzProtocol* protocol; - osTimerId timer; - SubGhzHopperState hopper_state; - uint8_t hopper_timeout; - uint32_t event_key_sequence; }; typedef struct { - string_t text; - uint16_t scene; - SubGhzProtocolCommon* protocol_result; - SubGhzHistory* history; - uint8_t frequency; - uint8_t temp_frequency; - uint32_t real_frequency; - + string_t frequency_str; + string_t preset_str; + string_t history_stat_str; + SubGhzReceiverHistory* history; uint16_t idx; uint16_t list_offset; uint16_t history_item; - bool menu; } SubghzReceiverModel; void subghz_receiver_set_callback( @@ -81,35 +60,6 @@ void subghz_receiver_set_callback( subghz_receiver->context = context; } -void subghz_receiver_set_protocol( - SubghzReceiver* subghz_receiver, - SubGhzProtocolCommon* protocol_result, - SubGhzProtocol* protocol) { - furi_assert(subghz_receiver); - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - model->protocol_result = protocol_result; - return true; - }); - subghz_receiver->protocol = protocol; -} - -SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver) { - furi_assert(subghz_receiver); - SubGhzProtocolCommon* result = NULL; - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - result = model->protocol_result; - return false; - }); - return result; -} - -void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker) { - furi_assert(subghz_receiver); - subghz_receiver->worker = worker; -} - static void subghz_receiver_update_offset(SubghzReceiver* subghz_receiver) { furi_assert(subghz_receiver); @@ -129,6 +79,38 @@ static void subghz_receiver_update_offset(SubghzReceiver* subghz_receiver) { }); } +void subghz_receiver_add_item_to_menu( + SubghzReceiver* subghz_receiver, + const char* name, + uint8_t type) { + furi_assert(subghz_receiver); + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + SubGhzReceiverMenuItem* item_menu = + SubGhzReceiverMenuItemArray_push_raw(model->history->data); + string_init_set_str(item_menu->item_str, name); + item_menu->type = type; + model->history_item++; + return true; + }); + subghz_receiver_update_offset(subghz_receiver); +} + +void subghz_receiver_add_data_statusbar( + SubghzReceiver* subghz_receiver, + const char* frequency_str, + const char* preset_str, + const char* history_stat_str) { + furi_assert(subghz_receiver); + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + string_set(model->frequency_str, frequency_str); + string_set(model->preset_str, preset_str); + string_set(model->history_stat_str, history_stat_str); + return true; + }); +} + static void subghz_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { canvas_set_color(canvas, ColorBlack); canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT); @@ -144,462 +126,113 @@ static void subghz_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scroll } 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); canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); - switch(model->scene) { - case ReceiverSceneMain: - for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { - size_t idx = CLAMP(i + model->list_offset, model->history_item, 0); - subghz_history_get_text_item_menu(model->history, str_buff, idx); - elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX); - if(model->idx == idx) { - subghz_receiver_draw_frame(canvas, i, scrollbar); - } else { - canvas_set_color(canvas, ColorBlack); - } - canvas_draw_icon( - canvas, - 1, - 2 + i * FRAME_HEIGHT, - ReceiverItemIcons[subghz_history_get_type_protocol(model->history, idx)]); - canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, string_get_cstr(str_buff)); - string_clean(str_buff); - } - if(scrollbar) { - elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item); - } - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); + elements_button_left(canvas, "Config"); - elements_button_left(canvas, "Config"); - canvas_draw_line(canvas, 46, 51, 125, 51); - if(subghz_history_get_text_space_left(model->history, str_buff)) { - canvas_draw_str(canvas, 54, 62, string_get_cstr(str_buff)); - } else { - if((model->real_frequency / 1000 % 10) > 4) { - frequency = model->real_frequency + 10000; - } else { - frequency = model->real_frequency; - } - snprintf( - buffer, - sizeof(buffer), - "%03ld.%02ld", - frequency / 1000000 % 1000, - frequency / 10000 % 100); - canvas_draw_str(canvas, 44, 62, buffer); - canvas_draw_str(canvas, 79, 62, "AM"); - canvas_draw_str(canvas, 96, 62, string_get_cstr(str_buff)); - } - break; - - case ReceiverSceneStart: + canvas_draw_str(canvas, 44, 62, string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 79, 62, string_get_cstr(model->preset_str)); + canvas_draw_str(canvas, 96, 62, string_get_cstr(model->history_stat_str)); + if(model->history_item == 0) { canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 63, 46, "Scanning..."); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - elements_button_left(canvas, "Config"); - if((model->real_frequency / 1000 % 10) > 4) { - frequency = model->real_frequency + 10000; - } else { - frequency = model->real_frequency; - } - snprintf( - buffer, - sizeof(buffer), - "%03ld.%02ld", - frequency / 1000000 % 1000, - frequency / 10000 % 100); - canvas_draw_str(canvas, 44, 62, buffer); - canvas_draw_str(canvas, 79, 62, "AM"); - subghz_history_get_text_space_left(model->history, str_buff); - canvas_draw_str(canvas, 96, 62, string_get_cstr(str_buff)); canvas_draw_line(canvas, 46, 51, 125, 51); - break; - - case ReceiverSceneConfig: - if(model->frequency < subghz_frequencies_count) { - snprintf( - buffer, - sizeof(buffer), - "Frequency: < %03ld.%03ldMHz >", - model->real_frequency / 1000000 % 1000, - model->real_frequency / 1000 % 1000); - canvas_draw_str(canvas, 0, 8, buffer); - canvas_draw_str(canvas, 0, 18, "Frequency Hopping: "); - } else { - canvas_draw_str(canvas, 0, 8, "Frequency: < --- >"); - canvas_draw_str(canvas, 0, 18, "Frequency Hopping: "); - } - canvas_draw_str(canvas, 0, 28, "Modulation: "); - - elements_button_center(canvas, "Save"); - break; - - case ReceiverSceneInfo: - canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 8, string_get_cstr(model->text)); - snprintf( - buffer, - sizeof(buffer), - "%03ld.%03ld", - subghz_history_get_frequency(model->history, model->idx) / 1000000 % 1000, - subghz_history_get_frequency(model->history, model->idx) / 1000 % 1000); - canvas_draw_str(canvas, 90, 8, buffer); - if(model->protocol_result && model->protocol_result->to_save_string && - strcmp(model->protocol_result->name, "KeeLoq")) { - elements_button_right(canvas, "Save"); - elements_button_center(canvas, "Send"); - } - break; - - default: - - break; + return; } + canvas_draw_line(canvas, 46, 51, 125, 51); + bool scrollbar = model->history_item > 4; + string_t str_buff; + string_init(str_buff); + + SubGhzReceiverMenuItem* item_menu; + + for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { + size_t idx = CLAMP(i + model->list_offset, model->history_item, 0); + item_menu = SubGhzReceiverMenuItemArray_get(model->history->data, idx); + string_set(str_buff, item_menu->item_str); + elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX); + if(model->idx == idx) { + subghz_receiver_draw_frame(canvas, i, scrollbar); + } else { + canvas_set_color(canvas, ColorBlack); + } + canvas_draw_icon(canvas, 1, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]); + canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, string_get_cstr(str_buff)); + string_clean(str_buff); + } + if(scrollbar) { + elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item); + } string_clear(str_buff); } -void subghz_receiver_history_full(void* context) { - furi_assert(context); - SubghzReceiver* subghz_receiver = context; - subghz_receiver->callback(SubghzReceverEventSendHistoryFull, subghz_receiver->context); - subghz_receiver->hopper_state = SubGhzHopperStateOFF; -} - bool subghz_receiver_input(InputEvent* event, void* context) { furi_assert(context); - - uint8_t scene = 0; SubghzReceiver* subghz_receiver = context; - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - scene = model->scene; - return false; - }); - bool can_be_saved = false; - - switch(scene) { - case ReceiverSceneMain: - if(event->key == InputKeyBack && event->type == InputTypeShort) { - 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 && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - if(model->idx != 0) model->idx--; - return true; - }); - } else if( - event->key == InputKeyDown && - (event->type == InputTypeShort || event->type == InputTypeRepeat)) { - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - if(model->idx != subghz_history_get_item(model->history) - 1) model->idx++; - return true; - }); - } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { - subghz_receiver->hopper_state = SubGhzHopperStatePause; - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - model->scene = ReceiverSceneConfig; - model->temp_frequency = model->frequency; - return true; - }); - subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context); - } else if(event->key == InputKeyOk && event->type == InputTypeShort) { - subghz_receiver->event_key_sequence = event->sequence; - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - string_clean(model->text); - model->protocol_result = subghz_protocol_get_by_name( - subghz_receiver->protocol, - subghz_history_get_name(model->history, model->idx)); - if(model->protocol_result->to_load_protocol != NULL) { - model->protocol_result->to_load_protocol( - model->protocol_result, - subghz_history_get_raw_data(model->history, model->idx)); - model->protocol_result->to_string(model->protocol_result, model->text); - model->scene = ReceiverSceneInfo; - } - return true; - }); - } - break; - - case ReceiverSceneInfo: + if(event->key == InputKeyBack && event->type == InputTypeShort) { + subghz_receiver->callback(SubghzReceverEventBack, subghz_receiver->context); + } else if( + event->key == InputKeyUp && + (event->type == InputTypeShort || event->type == InputTypeRepeat)) { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - can_be_saved = - (model->protocol_result && model->protocol_result->to_save_string && - strcmp(model->protocol_result->name, "KeeLoq")); - return false; + if(model->idx != 0) model->idx--; + return true; }); - if(event->key == InputKeyBack && event->type == InputTypeShort) { - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - subghz_rx_end(subghz_receiver->worker); - model->real_frequency = - subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]); - subghz_receiver->hopper_state = SubGhzHopperStateRunnig; - model->scene = ReceiverSceneMain; - return true; - }); - subghz_receiver->callback(SubghzReceverEventMain, subghz_receiver->context); - } else if(can_be_saved && event->key == InputKeyRight) { - subghz_receiver->callback(SubghzReceverEventSave, subghz_receiver->context); - return false; - } else if( - can_be_saved && event->key == InputKeyOk && event->type == InputTypePress && - subghz_receiver->event_key_sequence != event->sequence) { - subghz_receiver->hopper_state = SubGhzHopperStatePause; - subghz_rx_end(subghz_receiver->worker); - subghz_receiver->callback(SubghzReceverEventSendStart, subghz_receiver->context); - return true; - } else if( - can_be_saved && event->key == InputKeyOk && event->type == InputTypeRelease && - subghz_receiver->event_key_sequence != event->sequence) { - subghz_receiver->callback(SubghzReceverEventSendStop, subghz_receiver->context); - return true; - } - break; - - case ReceiverSceneConfig: - if(event->type != InputTypeShort) return false; - if(event->key == InputKeyBack) { - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - model->frequency = model->temp_frequency; - model->real_frequency = subghz_frequencies[model->frequency]; - subghz_receiver->hopper_state = SubGhzHopperStateRunnig; - if(subghz_history_get_item(model->history) == 0) { - model->scene = ReceiverSceneStart; - } else { - model->scene = ReceiverSceneMain; - } - return true; - }); - subghz_receiver->callback(SubghzReceverEventMain, subghz_receiver->context); - } else if(event->key == InputKeyOk) { - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - if(model->frequency < subghz_frequencies_count) { - subghz_rx_end(subghz_receiver->worker); - model->real_frequency = subghz_rx( - subghz_receiver->worker, subghz_frequencies[model->frequency]); - subghz_receiver->hopper_state = SubGhzHopperStateOFF; - } else { - osTimerStart(subghz_receiver->timer, 1024 / 10); - subghz_receiver->hopper_state = SubGhzHopperStateRunnig; - } - if(subghz_history_get_item(model->history) == 0) { - model->scene = ReceiverSceneStart; - } else { - model->scene = ReceiverSceneMain; - } - return true; - }); - subghz_receiver->callback(SubghzReceverEventMain, subghz_receiver->context); - } else { - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * 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) model->frequency++; - model_updated = true; - } - if(model_updated) { - model->real_frequency = subghz_frequencies[model->frequency]; - } - return model_updated; - }); - } - break; - - case ReceiverSceneStart: - if(event->type != InputTypeShort) return false; - if(event->key == InputKeyBack) { - return false; - } else if(event->key == InputKeyLeft) { - subghz_receiver->hopper_state = SubGhzHopperStatePause; - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - model->temp_frequency = model->frequency; - model->scene = ReceiverSceneConfig; - return true; - }); - subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context); - } - break; - - default: - break; - } - - subghz_receiver_update_offset(subghz_receiver); - if(scene != ReceiverSceneInfo) { + } else if( + event->key == InputKeyDown && + (event->type == InputTypeShort || event->type == InputTypeRepeat)) { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - if(subghz_history_get_text_space_left(model->history, NULL)) { - subghz_receiver_history_full(subghz_receiver); + if(model->idx != model->history_item - 1) model->idx++; + return true; + }); + } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { + subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context); + } else if(event->key == InputKeyOk && event->type == InputTypeShort) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + if(model->history_item != 0) { + subghz_receiver->callback(SubghzReceverEventOK, subghz_receiver->context); } return false; }); } + subghz_receiver_update_offset(subghz_receiver); + return true; } -void subghz_receiver_text_callback(string_t text, void* context) { - furi_assert(context); - SubghzReceiver* subghz_receiver = context; - - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - string_set(model->text, text); - model->scene = ReceiverSceneMain; - return true; - }); -} - -void subghz_receiver_protocol_callback(SubGhzProtocolCommon* parser, void* context) { - furi_assert(context); - SubghzReceiver* subghz_receiver = context; - - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - model->protocol_result = parser; - subghz_history_set_frequency_preset( - model->history, - model->history_item, - model->real_frequency, - FuriHalSubGhzPresetOok650Async); - subghz_history_add_to_history(model->history, parser); - - model->history_item = subghz_history_get_item(model->history); - model->scene = ReceiverSceneMain; - if(subghz_history_get_text_space_left(model->history, NULL)) { - subghz_receiver_history_full(subghz_receiver); - } - return true; - }); - subghz_protocol_reset(subghz_receiver->protocol); - subghz_receiver_update_offset(subghz_receiver); -} - -static void subghz_receiver_timer_callback(void* context) { - furi_assert(context); - SubghzReceiver* subghz_receiver = context; - - switch(subghz_receiver->hopper_state) { - case SubGhzHopperStatePause: - return; - break; - 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) { - 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) { - subghz_receiver->hopper_timeout = 10; - subghz_receiver->hopper_state = SubGhzHopperStateRSSITimeOut; - return false; - } - } else { - subghz_receiver->hopper_state = SubGhzHopperStateRunnig; - } - - // Select next frequency - if(model->frequency < COUNT_FREQUNCY_HOPPER - 1) { - model->frequency++; - } else { - model->frequency = 0; - } - - // Restart radio - furi_hal_subghz_idle(); - subghz_protocol_reset(subghz_receiver->protocol); - model->real_frequency = furi_hal_subghz_set_frequency_and_path( - subghz_frequencies_hopper[model->frequency]); - furi_hal_subghz_rx(); - - return true; - }); -} - void subghz_receiver_enter(void* context) { furi_assert(context); - SubghzReceiver* subghz_receiver = context; - //Start CC1101 Rx - subghz_begin(FuriHalSubGhzPresetOok650Async); - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - subghz_rx_end(subghz_receiver->worker); - model->frequency = subghz_frequencies_433_92; - model->real_frequency = - subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]); - if(subghz_history_get_item(model->history) == 0) { - model->scene = ReceiverSceneStart; - } else { - model->scene = ReceiverSceneMain; - } - return true; - }); - subghz_protocol_enable_dump( - subghz_receiver->protocol, subghz_receiver_protocol_callback, subghz_receiver); + //SubghzReceiver* subghz_receiver = context; } void subghz_receiver_exit(void* context) { furi_assert(context); SubghzReceiver* subghz_receiver = context; - osTimerStop(subghz_receiver->timer); with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - string_clean(model->text); - return true; + string_clean(model->frequency_str); + string_clean(model->preset_str); + string_clean(model->history_stat_str); + for + M_EACH(item_menu, model->history->data, SubGhzReceiverMenuItemArray_t) { + string_clear(item_menu->item_str); + item_menu->type = 0; + } + SubGhzReceiverMenuItemArray_clean(model->history->data); + model->idx = 0; + model->list_offset = 0; + model->history_item = 0; + return false; }); - // Stop CC1101 Rx - subghz_rx_end(subghz_receiver->worker); - subghz_sleep(); } SubghzReceiver* subghz_receiver_alloc() { @@ -616,14 +249,14 @@ SubghzReceiver* subghz_receiver_alloc() { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - string_init(model->text); - model->history = subghz_history_alloc(); + string_init(model->frequency_str); + string_init(model->preset_str); + string_init(model->history_stat_str); + model->history = furi_alloc(sizeof(SubGhzReceiverHistory)); + SubGhzReceiverMenuItemArray_init(model->history->data); return true; }); - subghz_receiver->timer = - osTimerNew(subghz_receiver_timer_callback, osTimerPeriodic, subghz_receiver, NULL); - subghz_receiver->hopper_state = SubGhzHopperStateOFF; return subghz_receiver; } @@ -632,11 +265,18 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver) { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - string_clear(model->text); - subghz_history_free(model->history); - return false; + string_clear(model->frequency_str); + string_clear(model->preset_str); + string_clear(model->history_stat_str); + for + M_EACH(item_menu, model->history->data, SubGhzReceiverMenuItemArray_t) { + string_clear(item_menu->item_str); + item_menu->type = 0; + } + SubGhzReceiverMenuItemArray_clear(model->history->data); + free(model->history); + return false; }); - osTimerDelete(subghz_receiver->timer); view_free(subghz_receiver->view); free(subghz_receiver); } @@ -646,43 +286,24 @@ View* subghz_receiver_get_view(SubghzReceiver* subghz_receiver) { return subghz_receiver->view; } -uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver) { +uint16_t subghz_receiver_get_idx_menu(SubghzReceiver* subghz_receiver) { furi_assert(subghz_receiver); - uint32_t frequency; + uint32_t idx = 0; with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - frequency = subghz_history_get_frequency(model->history, model->idx); + idx = model->idx; return false; }); - return frequency; + return idx; } -FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver) { +void subghz_receiver_set_idx_menu(SubghzReceiver* subghz_receiver, uint16_t idx) { furi_assert(subghz_receiver); - FuriHalSubGhzPreset preset; with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - preset = subghz_history_get_preset(model->history, model->idx); - return false; + model->idx = idx; + if(model->idx > 2) model->list_offset = idx - 2; + return true; }); - return preset; -} - -void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output) { - furi_assert(subghz_receiver); - uint32_t frequency; - uint32_t preset; - with_view_model( - subghz_receiver->view, (SubghzReceiverModel * model) { - frequency = subghz_history_get_frequency(model->history, model->idx); - preset = (uint32_t)subghz_history_get_preset(model->history, model->idx); - return false; - }); - - string_cat_printf( - output, - "Frequency: %d\n" - "Preset: %d\n", - (int)frequency, - (int)preset); -} + subghz_receiver_update_offset(subghz_receiver); +} \ No newline at end of file diff --git a/applications/subghz/views/subghz_receiver.h b/applications/subghz/views/subghz_receiver.h index 513f438c..be9a9ef1 100644 --- a/applications/subghz/views/subghz_receiver.h +++ b/applications/subghz/views/subghz_receiver.h @@ -1,21 +1,11 @@ #pragma once #include -#include -#include -#include -#include "../subghz_history.h" typedef enum { SubghzReceverEventOK, SubghzReceverEventConfig, - SubghzReceverEventMain, - SubghzReceverEventSave, SubghzReceverEventBack, - SubghzReceverEventMore, - SubghzReceverEventSendStart, - SubghzReceverEventSendStop, - SubghzReceverEventSendHistoryFull, } SubghzReceverEvent; typedef struct SubghzReceiver SubghzReceiver; @@ -33,17 +23,19 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver); View* subghz_receiver_get_view(SubghzReceiver* subghz_receiver); -void subghz_receiver_set_protocol( +void subghz_receiver_add_data_statusbar( SubghzReceiver* subghz_receiver, - SubGhzProtocolCommon* protocol_result, - SubGhzProtocol* protocol); + const char* frequency_str, + const char* preset_str, + const char* history_stat_str); -SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver); +void subghz_receiver_add_item_to_menu( + SubghzReceiver* subghz_receiver, + const char* name, + uint8_t type); -void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker); +uint16_t subghz_receiver_get_idx_menu(SubghzReceiver* subghz_receiver); -uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver); +void subghz_receiver_set_idx_menu(SubghzReceiver* subghz_receiver, uint16_t idx); -FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver); - -void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output); +void subghz_receiver_exit(void* context); \ No newline at end of file diff --git a/applications/subghz/views/subghz_transmitter.c b/applications/subghz/views/subghz_transmitter.c index 1dd4e7d9..6e29f5dd 100644 --- a/applications/subghz/views/subghz_transmitter.c +++ b/applications/subghz/views/subghz_transmitter.c @@ -1,13 +1,8 @@ #include "subghz_transmitter.h" #include "../subghz_i.h" -#include -#include -#include #include #include -#include -#include struct SubghzTransmitter { View* view; @@ -16,11 +11,10 @@ struct SubghzTransmitter { }; typedef struct { - string_t text; - uint16_t scene; - uint32_t real_frequency; - FuriHalSubGhzPreset preset; - SubGhzProtocolCommon* protocol; + string_t frequency_str; + string_t preset_str; + string_t key_str; + uint8_t show_button; } SubghzTransmitterModel; void subghz_transmitter_set_callback( @@ -33,24 +27,19 @@ void subghz_transmitter_set_callback( subghz_transmitter->context = context; } -void subghz_transmitter_set_protocol( +void subghz_transmitter_add_data_to_show( SubghzTransmitter* subghz_transmitter, - SubGhzProtocolCommon* protocol) { + const char* key_str, + const char* frequency_str, + const char* preset_str, + uint8_t show_button) { + furi_assert(subghz_transmitter); with_view_model( subghz_transmitter->view, (SubghzTransmitterModel * model) { - model->protocol = protocol; - return true; - }); -} - -void subghz_transmitter_set_frequency_preset( - SubghzTransmitter* subghz_transmitter, - uint32_t frequency, - FuriHalSubGhzPreset preset) { - with_view_model( - subghz_transmitter->view, (SubghzTransmitterModel * model) { - model->real_frequency = frequency; - model->preset = preset; + string_set(model->key_str, key_str); + string_set(model->frequency_str, frequency_str); + string_set(model->preset_str, preset_str); + model->show_button = show_button; return true; }); } @@ -87,26 +76,13 @@ static void subghz_transmitter_button_right(Canvas* canvas, const char* str) { } void subghz_transmitter_draw(Canvas* canvas, SubghzTransmitterModel* model) { - char buffer[64]; canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 8, string_get_cstr(model->text)); - snprintf( - buffer, - sizeof(buffer), - "%03ld.%03ld", - model->real_frequency / 1000000 % 1000, - model->real_frequency / 1000 % 1000); - canvas_draw_str(canvas, 90, 8, buffer); - - if(model->protocol && model->protocol->get_upload_protocol) { - if((!strcmp(model->protocol->name, "KeeLoq")) && - (!strcmp(subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) { - return; - } - subghz_transmitter_button_right(canvas, "Send"); - } + elements_multiline_text(canvas, 0, 8, string_get_cstr(model->key_str)); + canvas_draw_str(canvas, 78, 8, string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 113, 8, string_get_cstr(model->preset_str)); + if(model->show_button) subghz_transmitter_button_right(canvas, "Send"); } bool subghz_transmitter_input(InputEvent* event, void* context) { @@ -114,26 +90,25 @@ bool subghz_transmitter_input(InputEvent* event, void* context) { SubghzTransmitter* subghz_transmitter = context; bool can_be_sent = false; - if(event->key == InputKeyBack) { + if(event->key == InputKeyBack && event->type == InputTypeShort) { + with_view_model( + subghz_transmitter->view, (SubghzTransmitterModel * model) { + string_clean(model->frequency_str); + string_clean(model->preset_str); + string_clean(model->key_str); + model->show_button = 0; + return false; + }); return false; } with_view_model( subghz_transmitter->view, (SubghzTransmitterModel * model) { - if(model->protocol && model->protocol->get_upload_protocol) { - if((!strcmp(model->protocol->name, "KeeLoq")) && - (!strcmp( - subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) { - return false; - } + if(model->show_button) { can_be_sent = true; } - //can_be_sent = (model->protocol && model->protocol->get_upload_protocol); - string_clean(model->text); - model->protocol->to_string(model->protocol, model->text); return true; }); - //if(event->type != InputTypeShort) return false; if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) { subghz_transmitter->callback(SubghzTransmitterEventSendStart, subghz_transmitter->context); @@ -146,37 +121,14 @@ bool subghz_transmitter_input(InputEvent* event, void* context) { return true; } -void subghz_transmitter_text_callback(string_t text, void* context) { - furi_assert(context); - SubghzTransmitter* subghz_transmitter = context; - - with_view_model( - subghz_transmitter->view, (SubghzTransmitterModel * model) { - string_set(model->text, text); - model->scene = 0; - return true; - }); -} - void subghz_transmitter_enter(void* context) { furi_assert(context); - SubghzTransmitter* subghz_transmitter = context; - with_view_model( - subghz_transmitter->view, (SubghzTransmitterModel * model) { - string_clean(model->text); - model->protocol->to_string(model->protocol, model->text); - return true; - }); + // SubghzTransmitter* subghz_transmitter = context; } void subghz_transmitter_exit(void* context) { furi_assert(context); - SubghzTransmitter* subghz_transmitter = context; - with_view_model( - subghz_transmitter->view, (SubghzTransmitterModel * model) { - string_clean(model->text); - return true; - }); + // SubghzTransmitter* subghz_transmitter = context; } SubghzTransmitter* subghz_transmitter_alloc() { @@ -194,7 +146,9 @@ SubghzTransmitter* subghz_transmitter_alloc() { with_view_model( subghz_transmitter->view, (SubghzTransmitterModel * model) { - string_init(model->text); + string_init(model->frequency_str); + string_init(model->preset_str); + string_init(model->key_str); return true; }); return subghz_transmitter; @@ -205,7 +159,9 @@ void subghz_transmitter_free(SubghzTransmitter* subghz_transmitter) { with_view_model( subghz_transmitter->view, (SubghzTransmitterModel * model) { - string_clear(model->text); + string_clear(model->frequency_str); + string_clear(model->preset_str); + string_clear(model->key_str); return true; }); view_free(subghz_transmitter->view); diff --git a/applications/subghz/views/subghz_transmitter.h b/applications/subghz/views/subghz_transmitter.h index c4dd5982..8ddeaaf8 100644 --- a/applications/subghz/views/subghz_transmitter.h +++ b/applications/subghz/views/subghz_transmitter.h @@ -1,7 +1,6 @@ #pragma once #include -#include typedef enum { SubghzTransmitterEventSendStart, @@ -25,10 +24,9 @@ void subghz_transmitter_free(SubghzTransmitter* subghz_transmitter); View* subghz_transmitter_get_view(SubghzTransmitter* subghz_transmitter); -void subghz_transmitter_set_protocol( +void subghz_transmitter_add_data_to_show( SubghzTransmitter* subghz_transmitter, - SubGhzProtocolCommon* protocol); -void subghz_transmitter_set_frequency_preset( - SubghzTransmitter* subghz_transmitter, - uint32_t frequency, - FuriHalSubGhzPreset preset); + const char* key_str, + const char* frequency_str, + const char* preset_str, + uint8_t show_button); diff --git a/lib/subghz/protocols/subghz_protocol.c b/lib/subghz/protocols/subghz_protocol.c index c2e3efec..616139a2 100644 --- a/lib/subghz/protocols/subghz_protocol.c +++ b/lib/subghz/protocols/subghz_protocol.c @@ -10,6 +10,7 @@ #include "subghz_protocol_faac_slh.h" #include "subghz_protocol_nero_sketch.h" #include "subghz_protocol_star_line.h" +#include "subghz_protocol_nero_radio.h" #include "../subghz_keystore.h" @@ -27,6 +28,7 @@ typedef enum { SubGhzProtocolTypeFaacSLH, SubGhzProtocolTypeNeroSketch, SubGhzProtocolTypeStarLine, + SubGhzProtocolTypeNeroRadio, SubGhzProtocolTypeMax, } SubGhzProtocolType; @@ -88,6 +90,8 @@ SubGhzProtocol* subghz_protocol_alloc() { (SubGhzProtocolCommon*)subghz_protocol_nero_sketch_alloc(); instance->protocols[SubGhzProtocolTypeStarLine] = (SubGhzProtocolCommon*)subghz_protocol_star_line_alloc(instance->keystore); + instance->protocols[SubGhzProtocolTypeNeroRadio] = + (SubGhzProtocolCommon*)subghz_protocol_nero_radio_alloc(); return instance; } @@ -113,6 +117,8 @@ void subghz_protocol_free(SubGhzProtocol* instance) { (SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]); subghz_protocol_star_line_free( (SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]); + subghz_protocol_nero_radio_free( + (SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio]); subghz_keystore_free(instance->keystore); @@ -163,7 +169,6 @@ void subghz_protocol_enable_dump( } void subghz_protocol_load_nice_flor_s_file(SubGhzProtocol* instance, const char* file_name) { - // subghz_protocol_nice_flor_s_name_file(instance->nice_flor_s, file_name); subghz_protocol_nice_flor_s_name_file( (SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name); } @@ -191,6 +196,8 @@ void subghz_protocol_reset(SubGhzProtocol* instance) { (SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]); subghz_protocol_star_line_reset( (SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]); + subghz_protocol_nero_radio_reset( + (SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio]); } void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration) { @@ -220,4 +227,8 @@ void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t durati duration); subghz_protocol_star_line_parse( (SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine], level, duration); + subghz_protocol_nero_radio_parse( + (SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio], + level, + duration); } diff --git a/lib/subghz/protocols/subghz_protocol_gate_tx.h b/lib/subghz/protocols/subghz_protocol_gate_tx.h index 79f3b9db..5fc1001e 100644 --- a/lib/subghz/protocols/subghz_protocol_gate_tx.h +++ b/lib/subghz/protocols/subghz_protocol_gate_tx.h @@ -18,7 +18,7 @@ void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance); /** Get upload protocol * - * @param instance - SubGhzProtocolCame instance + * @param instance - SubGhzProtocolGateTX instance * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ diff --git a/lib/subghz/protocols/subghz_protocol_keeloq.c b/lib/subghz/protocols/subghz_protocol_keeloq.c index 875e6002..ccb2e1ae 100644 --- a/lib/subghz/protocols/subghz_protocol_keeloq.c +++ b/lib/subghz/protocols/subghz_protocol_keeloq.c @@ -398,9 +398,9 @@ void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t outp string_cat_printf( output, "%s %dbit\r\n" - "Key:0x%lX%lX\r\n" - "Fix:0x%08lX Cnt:%04X\r\n" - "Hop:0x%08lX Btn:%02lX\r\n" + "Key:%08lX%08lX\r\n" + "Fix:0x%08lX Cnt:%04X\r\n" + "Hop:0x%08lX Btn:%02lX\r\n" "MF:%s\r\n" "Sn:0x%07lX \r\n", instance->common.name, diff --git a/lib/subghz/protocols/subghz_protocol_keeloq.h b/lib/subghz/protocols/subghz_protocol_keeloq.h index 1cbacd8c..313b7cb3 100644 --- a/lib/subghz/protocols/subghz_protocol_keeloq.h +++ b/lib/subghz/protocols/subghz_protocol_keeloq.h @@ -49,7 +49,7 @@ uint64_t subghz_protocol_keeloq_gen_key(void* context); /** Get upload protocol * - * @param instance - SubGhzProtocolCame instance + * @param instance - SubGhzProtocolKeeloq instance * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ diff --git a/lib/subghz/protocols/subghz_protocol_nero_radio.c b/lib/subghz/protocols/subghz_protocol_nero_radio.c new file mode 100644 index 00000000..2a03d722 --- /dev/null +++ b/lib/subghz/protocols/subghz_protocol_nero_radio.c @@ -0,0 +1,280 @@ +#include "subghz_protocol_nero_radio.h" + +struct SubGhzProtocolNeroRadio { + SubGhzProtocolCommon common; +}; + +SubGhzProtocolNeroRadio* subghz_protocol_nero_radio_alloc(void) { + SubGhzProtocolNeroRadio* instance = furi_alloc(sizeof(SubGhzProtocolNeroRadio)); + + instance->common.name = "Nero Radio"; + instance->common.code_min_count_bit_for_found = 55; + instance->common.te_short = 200; + instance->common.te_long = 400; + instance->common.te_delta = 80; + instance->common.type_protocol = TYPE_PROTOCOL_STATIC; + instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nero_radio_to_str; + instance->common.to_save_string = + (SubGhzProtocolCommonGetStrSave)subghz_protocol_nero_radio_to_save_str; + instance->common.to_load_protocol_from_file = + (SubGhzProtocolCommonLoadFromFile)subghz_protocol_nero_radio_to_load_protocol_from_file; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nero_radio_to_load_protocol; + instance->common.get_upload_protocol = + (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_nero_radio_send_key; + + return instance; +} + +void subghz_protocol_nero_radio_free(SubGhzProtocolNeroRadio* instance) { + furi_assert(instance); + free(instance); +} + +bool subghz_protocol_nero_radio_send_key( + SubGhzProtocolNeroRadio* instance, + SubGhzProtocolCommonEncoder* encoder) { + furi_assert(instance); + furi_assert(encoder); + size_t index = 0; + encoder->size_upload = 2 + 47 * 2 + 2 + (instance->common.code_last_count_bit * 2); + if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false; + + //Send header + encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short); + encoder->upload[index++] = + level_duration_make(false, (uint32_t)instance->common.te_short * 37); + for(uint8_t i = 0; i < 47; i++) { + encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short); + encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short); + } + + //Send start bit + encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short * 4); + encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short); + + //Send key data + for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) { + if(bit_read(instance->common.code_last_found, i - 1)) { + //send bit 1 + encoder->upload[index++] = + level_duration_make(true, (uint32_t)instance->common.te_long); + encoder->upload[index++] = + level_duration_make(false, (uint32_t)instance->common.te_short); + } else { + //send bit 0 + encoder->upload[index++] = + level_duration_make(true, (uint32_t)instance->common.te_short); + encoder->upload[index++] = + level_duration_make(false, (uint32_t)instance->common.te_long); + } + } + + return true; +} + +void subghz_protocol_nero_radio_reset(SubGhzProtocolNeroRadio* instance) { + instance->common.parser_step = 0; +} + +/** Analysis of received data + * + * @param instance SubGhzProtocolNeroRadio instance + */ +// void subghz_protocol_nero_radio_check_remote_controller(SubGhzProtocolNeroRadio* instance) { +// //пока не понятно с серийником, но код статический +// // uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_found, instance->common.code_count_bit); +// // uint32_t code_fix = code_found_reverse & 0xFFFFFFFF; +// // //uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF; + +// // instance->common.serial = code_fix & 0xFFFFFFF; +// // instance->common.btn = (code_fix >> 28) & 0x0F; + +// //if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context); + +// } + +void subghz_protocol_nero_radio_parse( + SubGhzProtocolNeroRadio* instance, + bool level, + uint32_t duration) { + switch(instance->common.parser_step) { + case 0: + if((level) && + (DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) { + instance->common.parser_step = 1; + instance->common.te_last = duration; + instance->common.header_count = 0; + } else { + instance->common.parser_step = 0; + } + break; + case 1: + if(level) { + if((DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) || + (DURATION_DIFF(duration, instance->common.te_short * 4) < + instance->common.te_delta)) { + instance->common.te_last = duration; + } else { + instance->common.parser_step = 0; + } + } else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) { + if(DURATION_DIFF(instance->common.te_last, instance->common.te_short) < + instance->common.te_delta) { + // Found header + instance->common.header_count++; + break; + } else if( + DURATION_DIFF(instance->common.te_last, instance->common.te_short * 4) < + instance->common.te_delta) { + // Found start bit + if(instance->common.header_count > 40) { + instance->common.parser_step = 2; + instance->common.code_found = 0; + instance->common.code_count_bit = 0; + } else { + instance->common.parser_step = 0; + } + } else { + instance->common.parser_step = 0; + } + } else { + instance->common.parser_step = 0; + } + break; + case 2: + if(level) { + instance->common.te_last = duration; + instance->common.parser_step = 3; + } else { + instance->common.parser_step = 0; + } + break; + case 3: + if(!level) { + if(duration >= (instance->common.te_short * 10 + instance->common.te_delta * 2)) { + //Found stop bit + instance->common.parser_step = 0; + if(instance->common.code_count_bit >= + instance->common.code_min_count_bit_for_found) { + instance->common.code_last_found = instance->common.code_found; + instance->common.code_last_count_bit = instance->common.code_count_bit; + if(instance->common.callback) + instance->common.callback( + (SubGhzProtocolCommon*)instance, instance->common.context); + } + instance->common.code_found = 0; + instance->common.code_count_bit = 0; + instance->common.parser_step = 0; + break; + } else if( + (DURATION_DIFF(instance->common.te_last, instance->common.te_short) < + instance->common.te_delta) && + (DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) { + subghz_protocol_common_add_bit(&instance->common, 0); + instance->common.parser_step = 2; + } else if( + (DURATION_DIFF(instance->common.te_last, instance->common.te_long) < + instance->common.te_delta) && + (DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) { + subghz_protocol_common_add_bit(&instance->common, 1); + instance->common.parser_step = 2; + } else { + instance->common.parser_step = 0; + } + } else { + instance->common.parser_step = 0; + } + break; + } +} + +void subghz_protocol_nero_radio_to_str(SubGhzProtocolNeroRadio* instance, string_t output) { + uint32_t code_found_hi = instance->common.code_last_found >> 32; + uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff; + + uint64_t code_found_reverse = subghz_protocol_common_reverse_key( + instance->common.code_last_found, instance->common.code_last_count_bit); + + uint32_t code_found_reverse_hi = code_found_reverse >> 32; + uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; + + string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Yek:0x%lX%08lX\r\n", + instance->common.name, + instance->common.code_last_count_bit, + code_found_hi, + code_found_lo, + code_found_reverse_hi, + code_found_reverse_lo); +} + +void subghz_protocol_nero_radio_to_save_str(SubGhzProtocolNeroRadio* instance, string_t output) { + uint32_t code_found_hi = instance->common.code_last_found >> 32; + uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff; + + string_printf( + output, + "Protocol: %s\n" + "Bit: %d\n" + "Key: %08lX%08lX\n", + instance->common.name, + instance->common.code_last_count_bit, + code_found_hi, + code_found_lo); +} + +bool subghz_protocol_nero_radio_to_load_protocol_from_file( + FileWorker* file_worker, + SubGhzProtocolNeroRadio* instance) { + bool loaded = false; + string_t temp_str; + string_init(temp_str); + int res = 0; + int data = 0; + + do { + // Read and parse bit data from 2nd line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + res = sscanf(string_get_cstr(temp_str), "Bit: %d\n", &data); + if(res != 1) { + break; + } + instance->common.code_last_count_bit = (uint8_t)data; + + // Read and parse key data from 3nd line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + // strlen("Key: ") = 5 + string_right(temp_str, 5); + + uint8_t buf_key[8] = {0}; + if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) { + break; + } + + for(uint8_t i = 0; i < 8; i++) { + instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i]; + } + + loaded = true; + } while(0); + + string_clear(temp_str); + + return loaded; +} + +void subghz_decoder_nero_radio_to_load_protocol(SubGhzProtocolNeroRadio* instance, void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; +} \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_nero_radio.h b/lib/subghz/protocols/subghz_protocol_nero_radio.h new file mode 100644 index 00000000..11f13201 --- /dev/null +++ b/lib/subghz/protocols/subghz_protocol_nero_radio.h @@ -0,0 +1,72 @@ +#pragma once + +#include "subghz_protocol_common.h" + +typedef struct SubGhzProtocolNeroRadio SubGhzProtocolNeroRadio; + +/** Allocate SubGhzProtocolNeroRadio + * + * @return SubGhzProtocolNeroRadio* + */ +SubGhzProtocolNeroRadio* subghz_protocol_nero_radio_alloc(); + +/** Free SubGhzProtocolNeroRadio + * + * @param instance + */ +void subghz_protocol_nero_radio_free(SubGhzProtocolNeroRadio* instance); + +/** Get upload protocol + * + * @param instance - SubGhzProtocolNeroRadio instance + * @param encoder - SubGhzProtocolCommonEncoder encoder + * @return bool + */ +bool subghz_protocol_nero_radio_send_key(SubGhzProtocolNeroRadio* instance, SubGhzProtocolCommonEncoder* encoder); + +/** Reset internal state + * @param instance - SubGhzProtocolNeroRadio instance + */ +void subghz_protocol_nero_radio_reset(SubGhzProtocolNeroRadio* instance); + +/** Analysis of received data + * + * @param instance SubGhzProtocolNeroRadio instance + */ +void subghz_protocol_nero_radio_check_remote_controller(SubGhzProtocolNeroRadio* instance); + +/** Parse accepted duration + * + * @param instance - SubGhzProtocolNeroRadio instance + * @param data - LevelDuration level_duration + */ +void subghz_protocol_nero_radio_parse(SubGhzProtocolNeroRadio* instance, bool level, uint32_t duration); + +/** Outputting information from the parser + * + * @param instance - SubGhzProtocolNeroRadio* instance + * @param output - output string + */ +void subghz_protocol_nero_radio_to_str(SubGhzProtocolNeroRadio* instance, string_t output); + +/** Get a string to save the protocol + * + * @param instance - SubGhzProtocolNeroRadio instance + * @param output - the resulting string + */ +void subghz_protocol_nero_radio_to_save_str(SubGhzProtocolNeroRadio* instance, string_t output); + +/** Loading protocol from file + * + * @param file_worker - FileWorker file_worker + * @param instance - SubGhzProtocolNeroRadio instance + * @return bool + */ +bool subghz_protocol_nero_radio_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNeroRadio* instance); + +/** Loading protocol from bin data + * + * @param instance - SubGhzProtocolNeroRadio instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_nero_radio_to_load_protocol(SubGhzProtocolNeroRadio* instance, void* context); \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_nero_sketch.h b/lib/subghz/protocols/subghz_protocol_nero_sketch.h index e8a19a50..cdce88fd 100644 --- a/lib/subghz/protocols/subghz_protocol_nero_sketch.h +++ b/lib/subghz/protocols/subghz_protocol_nero_sketch.h @@ -18,7 +18,7 @@ void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance); /** Get upload protocol * - * @param instance - SubGhzProtocolCame instance + * @param instance - SubGhzProtocolNeroSketch instance * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ diff --git a/lib/subghz/protocols/subghz_protocol_nice_flo.h b/lib/subghz/protocols/subghz_protocol_nice_flo.h index 0f88636d..5c665cc2 100644 --- a/lib/subghz/protocols/subghz_protocol_nice_flo.h +++ b/lib/subghz/protocols/subghz_protocol_nice_flo.h @@ -18,7 +18,7 @@ void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance); /** Get upload protocol * - * @param instance - SubGhzProtocolCame instance + * @param instance - SubGhzProtocolNiceFlo instance * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ diff --git a/lib/subghz/protocols/subghz_protocol_princeton.c b/lib/subghz/protocols/subghz_protocol_princeton.c index 201f07d0..0cd60387 100644 --- a/lib/subghz/protocols/subghz_protocol_princeton.c +++ b/lib/subghz/protocols/subghz_protocol_princeton.c @@ -172,7 +172,7 @@ void subghz_decoder_princeton_parse( if(!level) { if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) { instance->common.parser_step = 1; - if(instance->common.code_count_bit >= + if(instance->common.code_count_bit == instance->common.code_min_count_bit_for_found) { if(instance->common.code_last_found == instance->common.code_found) { //instance->te = (instance->te+instance->common.te_last)/2; //Option 1 TE averaging diff --git a/lib/subghz/protocols/subghz_protocol_star_line.c b/lib/subghz/protocols/subghz_protocol_star_line.c index f8207348..001285f3 100644 --- a/lib/subghz/protocols/subghz_protocol_star_line.c +++ b/lib/subghz/protocols/subghz_protocol_star_line.c @@ -282,9 +282,9 @@ void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t string_cat_printf( output, "%s %dbit\r\n" - "Key:0x%lX%lX\r\n" - "Fix:0x%08lX Cnt:%04X\r\n" - "Hop:0x%08lX Btn:%02lX\r\n" + "Key:%08lX%08lX\r\n" + "Fix:0x%08lX Cnt:%04X\r\n" + "Hop:0x%08lX Btn:%02lX\r\n" "MF:%s\r\n" "Sn:0x%07lX \r\n", instance->common.name,