[FL-1758, FL-1790] SubGhz refactoring part 2, fix generation of a new GateTX serial (#696)
* WidGet: fix name Multiline String Element * SubGhz: rename SubGhzProtocol to SubGhzParser and bring it up * SubGhz: a new way to navigate in receiver views * SubGhz: fix syntax * WedGet: add forwarding input type to wedget button callback, fix using a callback in an application * SubGhz: add assertions and status checks * SubGhz: fix syntax * [FL-1790] SubGhz: fix GateTX * SubGhz: add 434.42 MHz frequency support * SubGhz: rename type protocol, add decoder stage names * SubGhz: fix navigation through received signals when changing scenes * SubGhz: fix 2-fsk config Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
@@ -118,7 +118,7 @@ static void widget_add_element(Widget* widget, WidgetElement* element) {
|
||||
});
|
||||
}
|
||||
|
||||
void widget_add_string_multi_element(
|
||||
void widget_add_string_multiline_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
@@ -127,9 +127,9 @@ void widget_add_string_multi_element(
|
||||
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);
|
||||
WidgetElement* string_multiline_element =
|
||||
widget_element_string_multiline_create(x, y, horizontal, vertical, font, text);
|
||||
widget_add_element(widget, string_multiline_element);
|
||||
}
|
||||
|
||||
void widget_add_string_element(
|
||||
|
@@ -34,7 +34,7 @@ View* widget_get_view(Widget* widget);
|
||||
* @param vertical - Align instance
|
||||
* @param font Font instance
|
||||
*/
|
||||
void widget_add_string_multi_element(
|
||||
void widget_add_string_multiline_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
|
@@ -32,26 +32,15 @@ static bool gui_button_input(InputEvent* event, WidgetElement* element) {
|
||||
|
||||
if(model->callback == NULL) return consumed;
|
||||
|
||||
if(event->key == InputKeyOk && event->type == InputTypePress &&
|
||||
model->button_type == GuiButtonTypeCenter) {
|
||||
model->callback(GuiButtonTypeCenterPress, model->context);
|
||||
if((model->button_type == GuiButtonTypeLeft) && (event->key == InputKeyLeft)) {
|
||||
model->callback(model->button_type, event->type, model->context);
|
||||
consumed = true;
|
||||
} else if(
|
||||
event->key == InputKeyOk && event->type == InputTypeRelease &&
|
||||
model->button_type == GuiButtonTypeCenter) {
|
||||
model->callback(GuiButtonTypeCenterRelease, model->context);
|
||||
} else if((model->button_type == GuiButtonTypeRight) && (event->key == InputKeyRight)) {
|
||||
model->callback(model->button_type, event->type, model->context);
|
||||
consumed = true;
|
||||
} else if((model->button_type == GuiButtonTypeCenter) && (event->key == InputKeyOk)) {
|
||||
model->callback(model->button_type, event->type, 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;
|
||||
} else if((model->button_type == GuiButtonTypeRight) && (event->key == InputKeyRight)) {
|
||||
model->callback(model->button_type, model->context);
|
||||
consumed = true;
|
||||
} else if((model->button_type == GuiButtonTypeCenter) && (event->key == InputKeyOk)) {
|
||||
model->callback(model->button_type, model->context);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
|
@@ -1,16 +1,15 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <gui/view.h>
|
||||
#include <input/input.h>
|
||||
|
||||
typedef enum {
|
||||
GuiButtonTypeLeft,
|
||||
GuiButtonTypeCenter,
|
||||
GuiButtonTypeRight,
|
||||
GuiButtonTypeCenterPress,
|
||||
GuiButtonTypeCenterRelease,
|
||||
} GuiButtonType;
|
||||
|
||||
typedef void (*ButtonCallback)(GuiButtonType result, void* context);
|
||||
typedef void (*ButtonCallback)(GuiButtonType result, InputType type, void* context);
|
||||
|
||||
typedef struct WidgetElement WidgetElement;
|
||||
typedef struct Widget Widget;
|
||||
@@ -31,7 +30,7 @@ struct WidgetElement {
|
||||
};
|
||||
|
||||
/* Create multi string element */
|
||||
WidgetElement* widget_element_string_multi_create(
|
||||
WidgetElement* widget_element_string_multiline_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
Align horizontal,
|
||||
|
@@ -9,12 +9,12 @@ typedef struct {
|
||||
Align vertical;
|
||||
Font font;
|
||||
string_t text;
|
||||
} GuiStringMultiModel;
|
||||
} GuiStringMultiLineModel;
|
||||
|
||||
static void gui_string_multi_draw(Canvas* canvas, WidgetElement* element) {
|
||||
static void gui_string_multiline_draw(Canvas* canvas, WidgetElement* element) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(element);
|
||||
GuiStringMultiModel* model = element->model;
|
||||
GuiStringMultiLineModel* model = element->model;
|
||||
|
||||
if(string_size(model->text)) {
|
||||
canvas_set_font(canvas, model->font);
|
||||
@@ -28,16 +28,16 @@ static void gui_string_multi_draw(Canvas* canvas, WidgetElement* element) {
|
||||
}
|
||||
}
|
||||
|
||||
static void gui_string_multi_free(WidgetElement* gui_string) {
|
||||
static void gui_string_multiline_free(WidgetElement* gui_string) {
|
||||
furi_assert(gui_string);
|
||||
|
||||
GuiStringMultiModel* model = gui_string->model;
|
||||
GuiStringMultiLineModel* model = gui_string->model;
|
||||
string_clear(model->text);
|
||||
free(gui_string->model);
|
||||
free(gui_string);
|
||||
}
|
||||
|
||||
WidgetElement* widget_element_string_multi_create(
|
||||
WidgetElement* widget_element_string_multiline_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
Align horizontal,
|
||||
@@ -47,7 +47,7 @@ WidgetElement* widget_element_string_multi_create(
|
||||
furi_assert(text);
|
||||
|
||||
// Allocate and init model
|
||||
GuiStringMultiModel* model = furi_alloc(sizeof(GuiStringMultiModel));
|
||||
GuiStringMultiLineModel* model = furi_alloc(sizeof(GuiStringMultiLineModel));
|
||||
model->x = x;
|
||||
model->y = y;
|
||||
model->horizontal = horizontal;
|
||||
@@ -59,8 +59,8 @@ WidgetElement* widget_element_string_multi_create(
|
||||
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->draw = gui_string_multiline_draw;
|
||||
gui_string->free = gui_string_multiline_free;
|
||||
gui_string->model = model;
|
||||
|
||||
return gui_string;
|
@@ -1,9 +1,10 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_delete_widget_callback(GuiButtonType result, void* context) {
|
||||
void nfc_scene_delete_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_delete_on_enter(void* context) {
|
||||
|
@@ -7,9 +7,11 @@ enum {
|
||||
NfcSceneDeviceInfoData,
|
||||
};
|
||||
|
||||
void nfc_scene_device_info_widget_callback(GuiButtonType result, void* context) {
|
||||
void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) {
|
||||
@@ -22,9 +24,11 @@ void nfc_scene_device_info_text_box_callback(void* context) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT);
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_bank_card_callback(GuiButtonType result, void* context) {
|
||||
void nfc_scene_device_info_bank_card_callback(GuiButtonType result, InputType type, void* context) {
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_on_enter(void* context) {
|
||||
|
@@ -1,10 +1,14 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
|
||||
void nfc_scene_read_emv_data_success_widget_callback(GuiButtonType result, void* context) {
|
||||
void nfc_scene_read_emv_data_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
|
@@ -46,7 +46,7 @@ void subghz_scene_add_to_history_callback(SubGhzProtocolCommon* parser, void* co
|
||||
|
||||
if(subghz_history_add_to_history(
|
||||
subghz->txrx->history, parser, subghz->txrx->frequency, subghz->txrx->preset)) {
|
||||
subghz_protocol_reset(subghz->txrx->protocol);
|
||||
subghz_parser_reset(subghz->txrx->parser);
|
||||
string_clean(str_buff);
|
||||
subghz_history_get_text_item_menu(
|
||||
subghz->txrx->history, str_buff, subghz_history_get_item(subghz->txrx->history) - 1);
|
||||
@@ -79,23 +79,18 @@ const void subghz_scene_receiver_on_enter(void* context) {
|
||||
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_parser_enable_dump(subghz->txrx->parser, subghz_scene_add_to_history_callback, subghz);
|
||||
|
||||
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;
|
||||
subghz_rx_end(subghz);
|
||||
};
|
||||
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);
|
||||
if((subghz->txrx->txrx_state == SubGhzTxRxStateIdle) ||
|
||||
(subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
|
||||
subghz_begin(subghz, subghz->txrx->preset);
|
||||
subghz_rx(subghz, subghz->txrx->frequency);
|
||||
}
|
||||
subghz_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen);
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewReceiver);
|
||||
}
|
||||
@@ -108,16 +103,15 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event
|
||||
case SubghzReceverEventBack:
|
||||
// Stop CC1101 Rx
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz_rx_end(subghz);
|
||||
subghz_sleep(subghz);
|
||||
};
|
||||
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);
|
||||
subghz_parser_enable_dump(subghz->txrx->parser, NULL, subghz);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
return true;
|
||||
@@ -129,6 +123,7 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event
|
||||
break;
|
||||
case SubghzReceverEventConfig:
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
|
||||
return true;
|
||||
break;
|
||||
@@ -137,7 +132,7 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) {
|
||||
subghz_hopper_update(subghz->txrx);
|
||||
subghz_hopper_update(subghz);
|
||||
subghz_scene_receiver_update_statusbar(subghz);
|
||||
}
|
||||
|
||||
|
@@ -1,15 +1,31 @@
|
||||
#include "../subghz_i.h"
|
||||
|
||||
void subghz_scene_receiver_info_callback(GuiButtonType result, void* context) {
|
||||
typedef enum {
|
||||
SubGhzSceneReceiverInfoCustomEventTxStart,
|
||||
SubGhzSceneReceiverInfoCustomEventTxStop,
|
||||
SubGhzSceneReceiverInfoCustomEventSave,
|
||||
} SubGhzSceneReceiverInfoCustomEvent;
|
||||
|
||||
void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, result);
|
||||
|
||||
if((result == GuiButtonTypeCenter) && (type == InputTypePress)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzSceneReceiverInfoCustomEventTxStart);
|
||||
} else if((result == GuiButtonTypeCenter) && (type == InputTypeRelease)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzSceneReceiverInfoCustomEventTxStop);
|
||||
} else if((result == GuiButtonTypeRight) && (type == InputTypeShort)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzSceneReceiverInfoCustomEventSave);
|
||||
}
|
||||
}
|
||||
|
||||
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->txrx->protocol_result = subghz_parser_get_by_name(
|
||||
subghz->txrx->parser,
|
||||
subghz_history_get_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen));
|
||||
|
||||
if(subghz->txrx->protocol_result->to_load_protocol != NULL) {
|
||||
@@ -51,7 +67,7 @@ const void subghz_scene_receiver_info_on_enter(void* context) {
|
||||
string_t text;
|
||||
string_init(text);
|
||||
subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, text);
|
||||
widget_add_string_multi_element(
|
||||
widget_add_string_multiline_element(
|
||||
subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(text));
|
||||
string_clear(text);
|
||||
|
||||
@@ -83,52 +99,46 @@ const void subghz_scene_receiver_info_on_enter(void* context) {
|
||||
const bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeCenterPress) {
|
||||
if(event.event == SubGhzSceneReceiverInfoCustomEventTxStart) {
|
||||
//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;
|
||||
subghz_rx_end(subghz);
|
||||
}
|
||||
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) {
|
||||
} else if(event.event == SubGhzSceneReceiverInfoCustomEventTxStop) {
|
||||
//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;
|
||||
subghz_begin(subghz, subghz->txrx->preset);
|
||||
subghz_rx(subghz, subghz->txrx->frequency);
|
||||
}
|
||||
if(subghz->txrx->hopper_state == SubGhzHopperStatePause) {
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
|
||||
}
|
||||
subghz->state_notifications = NOTIFICATION_RX_STATE;
|
||||
return true;
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
} else if(event.event == SubGhzSceneReceiverInfoCustomEventSave) {
|
||||
//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;
|
||||
subghz_rx_end(subghz);
|
||||
subghz_sleep(subghz);
|
||||
}
|
||||
if(!subghz_scene_receiver_info_update_parser(subghz)) {
|
||||
return false;
|
||||
@@ -141,7 +151,7 @@ const bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) {
|
||||
subghz_hopper_update(subghz->txrx);
|
||||
subghz_hopper_update(subghz);
|
||||
}
|
||||
switch(subghz->state_notifications) {
|
||||
case NOTIFICATION_TX_STATE:
|
||||
|
@@ -15,8 +15,7 @@ enum SubmenuIndex {
|
||||
|
||||
bool subghz_scene_set_type_submenu_to_find_protocol(void* context, const char* protocol_name) {
|
||||
SubGhz* subghz = context;
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->txrx->protocol, protocol_name);
|
||||
subghz->txrx->protocol_result = subghz_parser_get_by_name(subghz->txrx->parser, protocol_name);
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
string_set(subghz->error_str, "Protocol not found");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
@@ -142,7 +141,7 @@ const bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event
|
||||
case SubmenuIndexGateTX:
|
||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "GateTX")) {
|
||||
subghz->txrx->protocol_result->code_last_count_bit = 24;
|
||||
key = (key & 0x00F0FFFF) | 0xF << 16; //btn 0xF, 0xC, 0xA, 0x6
|
||||
key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?)
|
||||
subghz->txrx->protocol_result->code_last_found =
|
||||
subghz_protocol_common_reverse_key(
|
||||
key, subghz->txrx->protocol_result->code_last_count_bit);
|
||||
|
@@ -70,21 +70,19 @@ const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent ev
|
||||
if(event.event == SubghzTransmitterEventSendStart) {
|
||||
subghz->state_notifications = NOTIFICATION_TX_STATE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz_rx_end(subghz);
|
||||
}
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
if((subghz->txrx->txrx_state == SubGhzTxRxStateIdle) ||
|
||||
(subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
|
||||
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;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz_sleep(subghz);
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubghzTransmitterEventBack) {
|
||||
|
@@ -7,6 +7,7 @@ const char* const subghz_frequencies_text[] = {
|
||||
"387.00",
|
||||
"433.08",
|
||||
"433.92",
|
||||
"434.42",
|
||||
"434.78",
|
||||
"438.90",
|
||||
"464.00",
|
||||
@@ -26,6 +27,7 @@ const uint32_t subghz_frequencies[] = {
|
||||
387000000,
|
||||
433075000, /* LPD433 first */
|
||||
433920000, /* LPD433 mid */
|
||||
434420000,
|
||||
434775000, /* LPD433 last channels */
|
||||
438900000,
|
||||
464000000,
|
||||
@@ -156,24 +158,24 @@ SubGhz* subghz_alloc() {
|
||||
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->txrx_state = SubGhzTxRxStateSleep;
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
||||
subghz->txrx->history = subghz_history_alloc();
|
||||
subghz->txrx->worker = subghz_worker_alloc();
|
||||
subghz->txrx->protocol = subghz_protocol_alloc();
|
||||
subghz->txrx->parser = subghz_parser_alloc();
|
||||
subghz_worker_set_overrun_callback(
|
||||
subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset);
|
||||
subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_parser_reset);
|
||||
subghz_worker_set_pair_callback(
|
||||
subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse);
|
||||
subghz_worker_set_context(subghz->txrx->worker, subghz->txrx->protocol);
|
||||
subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_parser_parse);
|
||||
subghz_worker_set_context(subghz->txrx->worker, subghz->txrx->parser);
|
||||
|
||||
//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_parser_load_keeloq_file(subghz->txrx->parser, "/ext/subghz/keeloq_mfcodes");
|
||||
subghz_parser_load_nice_flor_s_file(subghz->txrx->parser, "/ext/subghz/nice_floor_s_rx");
|
||||
|
||||
//subghz_protocol_enable_dump_text(subghz->protocol, subghz_text_callback, subghz);
|
||||
//subghz_parser_enable_dump_text(subghz->protocol, subghz_text_callback, subghz);
|
||||
|
||||
return subghz;
|
||||
}
|
||||
@@ -232,7 +234,7 @@ void subghz_free(SubGhz* subghz) {
|
||||
subghz->gui = NULL;
|
||||
|
||||
//Worker & Protocol & History
|
||||
subghz_protocol_free(subghz->txrx->protocol);
|
||||
subghz_parser_free(subghz->txrx->parser);
|
||||
subghz_worker_free(subghz->txrx->worker);
|
||||
subghz_history_free(subghz->txrx->history);
|
||||
free(subghz->txrx);
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
#include <stream_buffer.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol.h>
|
||||
#include <lib/subghz/subghz_parser.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_princeton.h>
|
||||
|
||||
@@ -205,10 +205,10 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
|
||||
instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
|
||||
furi_check(instance->stream);
|
||||
|
||||
SubGhzProtocol* protocol = subghz_protocol_alloc();
|
||||
subghz_protocol_load_keeloq_file(protocol, "/ext/subghz/keeloq_mfcodes");
|
||||
subghz_protocol_load_nice_flor_s_file(protocol, "/ext/subghz/nice_floor_s_rx");
|
||||
subghz_protocol_enable_dump_text(protocol, subghz_cli_command_rx_text_callback, instance);
|
||||
SubGhzParser* parser = subghz_parser_alloc();
|
||||
subghz_parser_load_keeloq_file(parser, "/ext/subghz/keeloq_mfcodes");
|
||||
subghz_parser_load_nice_flor_s_file(parser, "/ext/subghz/nice_floor_s_rx");
|
||||
subghz_parser_enable_dump_text(parser, subghz_cli_command_rx_text_callback, instance);
|
||||
|
||||
// Configure radio
|
||||
furi_hal_subghz_reset();
|
||||
@@ -228,11 +228,11 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
|
||||
if(ret == sizeof(LevelDuration)) {
|
||||
if(level_duration_is_reset(level_duration)) {
|
||||
printf(".");
|
||||
subghz_protocol_reset(protocol);
|
||||
subghz_parser_reset(parser);
|
||||
} else {
|
||||
bool level = level_duration_get_level(level_duration);
|
||||
uint32_t duration = level_duration_get_duration(level_duration);
|
||||
subghz_protocol_parse(protocol, level, duration);
|
||||
subghz_parser_parse(parser, level, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,7 +244,7 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
|
||||
printf("\r\nPackets recieved %u\r\n", instance->packet_count);
|
||||
|
||||
// Cleanup
|
||||
subghz_protocol_free(protocol);
|
||||
subghz_parser_free(parser);
|
||||
vStreamBufferDelete(instance->stream);
|
||||
free(instance);
|
||||
}
|
||||
|
@@ -112,5 +112,3 @@ bool subghz_history_add_to_history(
|
||||
* @return SubGhzProtocolCommonLoad*
|
||||
*/
|
||||
SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
|
||||
|
||||
void subghz_hopper_update(void* context);
|
||||
|
@@ -10,19 +10,23 @@
|
||||
#include "../notification/notification.h"
|
||||
#include "views/subghz_receiver.h"
|
||||
|
||||
void subghz_begin(FuriHalSubGhzPreset preset) {
|
||||
void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset) {
|
||||
furi_assert(subghz);
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_idle();
|
||||
furi_hal_subghz_load_preset(preset);
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
}
|
||||
|
||||
uint32_t subghz_rx(void* context, uint32_t frequency) {
|
||||
furi_assert(context);
|
||||
uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) {
|
||||
furi_assert(subghz);
|
||||
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
SubGhzWorker* worker = context;
|
||||
furi_assert(
|
||||
subghz->txrx->txrx_state != SubGhzTxRxStateRx &&
|
||||
subghz->txrx->txrx_state != SubGhzTxRxStateSleep);
|
||||
|
||||
furi_hal_subghz_idle();
|
||||
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
|
||||
@@ -30,45 +34,54 @@ uint32_t subghz_rx(void* context, uint32_t frequency) {
|
||||
furi_hal_subghz_flush_rx();
|
||||
furi_hal_subghz_rx();
|
||||
|
||||
furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, worker);
|
||||
subghz_worker_start(worker);
|
||||
furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, subghz->txrx->worker);
|
||||
subghz_worker_start(subghz->txrx->worker);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateRx;
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t subghz_tx(uint32_t frequency) {
|
||||
uint32_t subghz_tx(SubGhz* subghz, uint32_t frequency) {
|
||||
furi_assert(subghz);
|
||||
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep);
|
||||
furi_hal_subghz_idle();
|
||||
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
hal_gpio_write(&gpio_cc1101_g0, true);
|
||||
furi_hal_subghz_tx();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateTx;
|
||||
return value;
|
||||
}
|
||||
|
||||
void subghz_idle(void) {
|
||||
void subghz_idle(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep);
|
||||
furi_hal_subghz_idle();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
}
|
||||
|
||||
void subghz_rx_end(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzWorker* worker = context;
|
||||
|
||||
if(subghz_worker_is_running(worker)) {
|
||||
subghz_worker_stop(worker);
|
||||
void subghz_rx_end(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(subghz->txrx->txrx_state == SubGhzTxRxStateRx);
|
||||
if(subghz_worker_is_running(subghz->txrx->worker)) {
|
||||
subghz_worker_stop(subghz->txrx->worker);
|
||||
furi_hal_subghz_stop_async_rx();
|
||||
}
|
||||
furi_hal_subghz_idle();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
}
|
||||
|
||||
void subghz_sleep(void) {
|
||||
void subghz_sleep(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
furi_hal_subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
|
||||
}
|
||||
|
||||
void subghz_frequency_preset_to_str(void* context, string_t output) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
static void subghz_frequency_preset_to_str(SubGhz* subghz, string_t output) {
|
||||
furi_assert(subghz);
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Frequency: %d\n"
|
||||
@@ -77,9 +90,9 @@ void subghz_frequency_preset_to_str(void* context, string_t output) {
|
||||
(int)subghz->txrx->preset);
|
||||
}
|
||||
|
||||
void subghz_tx_start(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
void subghz_tx_start(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
|
||||
subghz->txrx->encoder = subghz_protocol_encoder_common_alloc();
|
||||
subghz->txrx->encoder->repeat = 200; //max repeat with the button held down
|
||||
//get upload
|
||||
@@ -87,14 +100,14 @@ void subghz_tx_start(void* context) {
|
||||
if(subghz->txrx->protocol_result->get_upload_protocol(
|
||||
subghz->txrx->protocol_result, subghz->txrx->encoder)) {
|
||||
if(subghz->txrx->preset) {
|
||||
subghz_begin(subghz->txrx->preset);
|
||||
subghz_begin(subghz, subghz->txrx->preset);
|
||||
} else {
|
||||
subghz_begin(FuriHalSubGhzPresetOok270Async);
|
||||
subghz_begin(subghz, FuriHalSubGhzPresetOok270Async);
|
||||
}
|
||||
if(subghz->txrx->frequency) {
|
||||
subghz_tx(subghz->txrx->frequency);
|
||||
subghz_tx(subghz, subghz->txrx->frequency);
|
||||
} else {
|
||||
subghz_tx(433920000);
|
||||
subghz_tx(subghz, 433920000);
|
||||
}
|
||||
|
||||
//Start TX
|
||||
@@ -104,15 +117,15 @@ void subghz_tx_start(void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_tx_stop(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
void subghz_tx_stop(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(subghz->txrx->txrx_state == SubGhzTxRxStateTx);
|
||||
//Stop TX
|
||||
furi_hal_subghz_stop_async_tx();
|
||||
subghz_protocol_encoder_common_free(subghz->txrx->encoder);
|
||||
furi_hal_subghz_idle();
|
||||
subghz_idle(subghz);
|
||||
//if protocol dynamic then we save the last upload
|
||||
if(subghz->txrx->protocol_result->type_protocol == TYPE_PROTOCOL_DYNAMIC) {
|
||||
if(subghz->txrx->protocol_result->type_protocol == SubGhzProtocolCommonTypeDynamic) {
|
||||
subghz_save_protocol_to_file(subghz, subghz->text_store);
|
||||
}
|
||||
notification_message(subghz->notifications, &sequence_reset_red);
|
||||
@@ -164,7 +177,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
// strlen("Protocol: ") = 10
|
||||
string_right(temp_str, 10);
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str));
|
||||
subghz_parser_get_by_name(subghz->txrx->parser, string_get_cstr(temp_str));
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
break;
|
||||
}
|
||||
@@ -186,10 +199,10 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
return loaded;
|
||||
}
|
||||
|
||||
bool subghz_save_protocol_to_file(void* context, const char* dev_name) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(subghz->txrx->protocol_result);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
string_t dev_file_name;
|
||||
string_init(dev_file_name);
|
||||
@@ -308,7 +321,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) {
|
||||
// strlen("Protocol: ") = 10
|
||||
string_right(temp_str, 10);
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str));
|
||||
subghz_parser_get_by_name(subghz->txrx->parser, string_get_cstr(temp_str));
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
break;
|
||||
}
|
||||
@@ -342,11 +355,10 @@ uint32_t subghz_random_serial(void) {
|
||||
return (uint32_t)rand();
|
||||
}
|
||||
|
||||
void subghz_hopper_update(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTxRx* txrx = context;
|
||||
void subghz_hopper_update(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
|
||||
switch(txrx->hopper_state) {
|
||||
switch(subghz->txrx->hopper_state) {
|
||||
case SubGhzHopperStateOFF:
|
||||
return;
|
||||
break;
|
||||
@@ -354,8 +366,8 @@ void subghz_hopper_update(void* context) {
|
||||
return;
|
||||
break;
|
||||
case SubGhzHopperStateRSSITimeOut:
|
||||
if(txrx->hopper_timeout != 0) {
|
||||
txrx->hopper_timeout--;
|
||||
if(subghz->txrx->hopper_timeout != 0) {
|
||||
subghz->txrx->hopper_timeout--;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -363,35 +375,33 @@ void subghz_hopper_update(void* context) {
|
||||
break;
|
||||
}
|
||||
float rssi = -127.0f;
|
||||
if(txrx->hopper_state != SubGhzHopperStateRSSITimeOut) {
|
||||
if(subghz->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;
|
||||
subghz->txrx->hopper_timeout = 10;
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateRSSITimeOut;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
txrx->hopper_state = SubGhzHopperStateRunnig;
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
|
||||
}
|
||||
|
||||
// Select next frequency
|
||||
if(txrx->hopper_idx_frequency < subghz_hopper_frequencies_count - 1) {
|
||||
txrx->hopper_idx_frequency++;
|
||||
if(subghz->txrx->hopper_idx_frequency < subghz_hopper_frequencies_count - 1) {
|
||||
subghz->txrx->hopper_idx_frequency++;
|
||||
} else {
|
||||
txrx->hopper_idx_frequency = 0;
|
||||
subghz->txrx->hopper_idx_frequency = 0;
|
||||
}
|
||||
|
||||
if(txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(txrx->worker);
|
||||
txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz);
|
||||
};
|
||||
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;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
subghz_parser_reset(subghz->txrx->parser);
|
||||
subghz->txrx->frequency = subghz_hopper_frequencies[subghz->txrx->hopper_idx_frequency];
|
||||
subghz_rx(subghz, subghz->txrx->frequency);
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,8 @@
|
||||
#include <subghz/scenes/subghz_scene.h>
|
||||
|
||||
#include <lib/subghz/subghz_worker.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol.h>
|
||||
|
||||
#include <lib/subghz/subghz_parser.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
||||
#include "subghz_history.h"
|
||||
|
||||
@@ -47,6 +48,7 @@ typedef enum {
|
||||
SubGhzTxRxStateIdle,
|
||||
SubGhzTxRxStateRx,
|
||||
SubGhzTxRxStateTx,
|
||||
SubGhzTxRxStateSleep,
|
||||
} SubGhzTxRxState;
|
||||
|
||||
/** SubGhzHopperState state */
|
||||
@@ -59,7 +61,7 @@ typedef enum {
|
||||
|
||||
struct SubGhzTxRx {
|
||||
SubGhzWorker* worker;
|
||||
SubGhzProtocol* protocol;
|
||||
SubGhzParser* parser;
|
||||
SubGhzProtocolCommon* protocol_result;
|
||||
SubGhzProtocolCommonEncoder* encoder;
|
||||
uint32_t frequency;
|
||||
@@ -115,15 +117,14 @@ typedef enum {
|
||||
SubGhzViewTestPacket,
|
||||
} SubGhzView;
|
||||
|
||||
void subghz_begin(FuriHalSubGhzPreset preset);
|
||||
uint32_t subghz_rx(void* context, uint32_t frequency);
|
||||
uint32_t subghz_tx(uint32_t frequency);
|
||||
void subghz_idle(void);
|
||||
void subghz_rx_end(void* context);
|
||||
void subghz_sleep(void);
|
||||
void subghz_tx_start(void* context);
|
||||
void subghz_tx_stop(void* context);
|
||||
void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset);
|
||||
uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency);
|
||||
void subghz_rx_end(SubGhz* subghz);
|
||||
void subghz_sleep(SubGhz* subghz);
|
||||
void subghz_tx_start(SubGhz* subghz);
|
||||
void subghz_tx_stop(SubGhz* subghz);
|
||||
bool subghz_key_load(SubGhz* subghz, const char* file_path);
|
||||
bool subghz_save_protocol_to_file(void* context, const char* dev_name);
|
||||
bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name);
|
||||
bool subghz_load_protocol_from_file(SubGhz* subghz);
|
||||
uint32_t subghz_random_serial(void);
|
||||
void subghz_hopper_update(SubGhz* subghz);
|
||||
|
@@ -29,9 +29,9 @@ struct SubGhzReceiverHistory {
|
||||
typedef struct SubGhzReceiverHistory SubGhzReceiverHistory;
|
||||
|
||||
static const Icon* ReceiverItemIcons[] = {
|
||||
[TYPE_PROTOCOL_UNKNOWN] = &I_Quest_7x8,
|
||||
[TYPE_PROTOCOL_STATIC] = &I_Unlock_7x8,
|
||||
[TYPE_PROTOCOL_DYNAMIC] = &I_Lock_7x8,
|
||||
[SubGhzProtocolCommonTypeUnknown] = &I_Quest_7x8,
|
||||
[SubGhzProtocolCommonTypeStatic] = &I_Unlock_7x8,
|
||||
[SubGhzProtocolCommonTypeDynamic] = &I_Lock_7x8,
|
||||
};
|
||||
|
||||
struct SubghzReceiver {
|
||||
@@ -90,7 +90,13 @@ void subghz_receiver_add_item_to_menu(
|
||||
SubGhzReceiverMenuItemArray_push_raw(model->history->data);
|
||||
string_init_set_str(item_menu->item_str, name);
|
||||
item_menu->type = type;
|
||||
model->history_item++;
|
||||
if((model->idx == model->history_item - 1)) {
|
||||
model->history_item++;
|
||||
model->idx++;
|
||||
} else {
|
||||
model->history_item++;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
subghz_receiver_update_offset(subghz_receiver);
|
||||
|
Reference in New Issue
Block a user