[FL-1758] SubGhz refactoring part 1 (#689)
* 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: あく <alleteam@gmail.com>
This commit is contained in:
parent
fbccb9fbaf
commit
f385340b2e
@ -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, 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)) {
|
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);
|
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) {
|
View* variable_item_list_get_view(VariableItemList* variable_item_list) {
|
||||||
furi_assert(variable_item_list);
|
furi_assert(variable_item_list);
|
||||||
return variable_item_list->view;
|
return variable_item_list->view;
|
||||||
|
@ -18,6 +18,9 @@ VariableItemList* variable_item_list_alloc();
|
|||||||
* @param variable_item_list VariableItemList instance
|
* @param variable_item_list VariableItemList instance
|
||||||
*/
|
*/
|
||||||
void variable_item_list_free(VariableItemList* variable_item_list);
|
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);
|
View* variable_item_list_get_view(VariableItemList* variable_item_list);
|
||||||
|
|
||||||
/** Add item to VariableItemList
|
/** Add item to VariableItemList
|
||||||
|
@ -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(
|
void widget_add_string_element(
|
||||||
Widget* widget,
|
Widget* widget,
|
||||||
uint8_t x,
|
uint8_t x,
|
||||||
|
@ -26,6 +26,23 @@ void widget_clear(Widget* widget);
|
|||||||
*/
|
*/
|
||||||
View* widget_get_view(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
|
/** Add String Element
|
||||||
* @param widget Widget instance
|
* @param widget Widget instance
|
||||||
* @param x - x coordinate
|
* @param x - x coordinate
|
||||||
|
@ -30,7 +30,18 @@ static bool gui_button_input(InputEvent* event, WidgetElement* element) {
|
|||||||
GuiButtonModel* model = element->model;
|
GuiButtonModel* model = element->model;
|
||||||
bool consumed = false;
|
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)) {
|
if((model->button_type == GuiButtonTypeLeft) && (event->key == InputKeyLeft)) {
|
||||||
model->callback(model->button_type, model->context);
|
model->callback(model->button_type, model->context);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
@ -6,6 +6,8 @@ typedef enum {
|
|||||||
GuiButtonTypeLeft,
|
GuiButtonTypeLeft,
|
||||||
GuiButtonTypeCenter,
|
GuiButtonTypeCenter,
|
||||||
GuiButtonTypeRight,
|
GuiButtonTypeRight,
|
||||||
|
GuiButtonTypeCenterPress,
|
||||||
|
GuiButtonTypeCenterRelease,
|
||||||
} GuiButtonType;
|
} GuiButtonType;
|
||||||
|
|
||||||
typedef void (*ButtonCallback)(GuiButtonType result, void* context);
|
typedef void (*ButtonCallback)(GuiButtonType result, void* context);
|
||||||
@ -28,6 +30,15 @@ struct WidgetElement {
|
|||||||
Widget* parent;
|
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 */
|
/* Create string element */
|
||||||
WidgetElement* widget_element_string_create(
|
WidgetElement* widget_element_string_create(
|
||||||
uint8_t x,
|
uint8_t x,
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
#include "widget_element_i.h"
|
||||||
|
#include <m-string.h>
|
||||||
|
#include <gui/elements.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
ADD_SCENE(subghz, start, Start)
|
ADD_SCENE(subghz, start, Start)
|
||||||
ADD_SCENE(subghz, receiver, Receiver)
|
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_name, SaveName)
|
||||||
ADD_SCENE(subghz, save_success, SaveSuccess)
|
ADD_SCENE(subghz, save_success, SaveSuccess)
|
||||||
ADD_SCENE(subghz, saved, Saved)
|
ADD_SCENE(subghz, saved, Saved)
|
||||||
ADD_SCENE(subghz, transmitter, Transmitter)
|
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, Test)
|
||||||
ADD_SCENE(subghz, test_static, TestStatic)
|
ADD_SCENE(subghz, test_static, TestStatic)
|
||||||
ADD_SCENE(subghz, test_carrier, TestCarrier)
|
ADD_SCENE(subghz, test_carrier, TestCarrier)
|
||||||
|
@ -1,21 +1,102 @@
|
|||||||
#include "../subghz_i.h"
|
#include "../subghz_i.h"
|
||||||
#include "../views/subghz_receiver.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) {
|
void subghz_scene_receiver_callback(SubghzReceverEvent event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, event);
|
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) {
|
const void subghz_scene_receiver_on_enter(void* context) {
|
||||||
SubGhz* subghz = 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;
|
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);
|
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) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
switch(event.event) {
|
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:
|
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;
|
return true;
|
||||||
break;
|
break;
|
||||||
case SubghzReceverEventSendStart:
|
case SubghzReceverEventOK:
|
||||||
subghz->state_notifications = NOTIFICATION_TX_STATE;
|
subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver);
|
||||||
subghz->frequency = subghz_receiver_get_frequency(subghz->subghz_receiver);
|
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo);
|
||||||
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;
|
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
case SubghzReceverEventConfig:
|
case SubghzReceverEventConfig:
|
||||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||||
return true;
|
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
|
||||||
break;
|
|
||||||
case SubghzReceverEventSendHistoryFull:
|
|
||||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if(event.type == SceneManagerEventTypeTick) {
|
} 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) {
|
switch(subghz->state_notifications) {
|
||||||
case NOTIFICATION_TX_STATE:
|
|
||||||
notification_message(subghz->notifications, &sequence_blink_red_10);
|
|
||||||
break;
|
|
||||||
case NOTIFICATION_RX_STATE:
|
case NOTIFICATION_RX_STATE:
|
||||||
notification_message(subghz->notifications, &sequence_blink_blue_10);
|
notification_message(subghz->notifications, &sequence_blink_blue_10);
|
||||||
break;
|
break;
|
||||||
|
156
applications/subghz/scenes/subghz_scene_receiver_config.c
Normal file
156
applications/subghz/scenes/subghz_scene_receiver_config.c
Normal file
@ -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);
|
||||||
|
}
|
163
applications/subghz/scenes/subghz_scene_receiver_info.c
Normal file
163
applications/subghz/scenes/subghz_scene_receiver_info.c
Normal file
@ -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);
|
||||||
|
}
|
@ -35,11 +35,13 @@ const bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent even
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) {
|
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);
|
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
//Error save
|
string_set(subghz->error_str, "No name file");
|
||||||
|
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,18 @@ enum SubmenuIndex {
|
|||||||
SubmenuIndexCAME12bit,
|
SubmenuIndexCAME12bit,
|
||||||
SubmenuIndexCAME24bit,
|
SubmenuIndexCAME24bit,
|
||||||
SubmenuIndexNeroSketch,
|
SubmenuIndexNeroSketch,
|
||||||
|
SubmenuIndexNeroRadio,
|
||||||
SubmenuIndexGateTX,
|
SubmenuIndexGateTX,
|
||||||
SubmenuIndexDoorHan,
|
SubmenuIndexDoorHan,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool subghz_scene_set_type_submenu_to_find_protocol(void* context, const char* protocol_name) {
|
bool subghz_scene_set_type_submenu_to_find_protocol(void* context, const char* protocol_name) {
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
subghz->protocol_result = subghz_protocol_get_by_name(subghz->protocol, protocol_name);
|
subghz->txrx->protocol_result =
|
||||||
if(subghz->protocol_result == NULL) {
|
subghz_protocol_get_by_name(subghz->txrx->protocol, protocol_name);
|
||||||
//show error
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -62,6 +65,8 @@ const void subghz_scene_set_type_on_enter(void* context) {
|
|||||||
subghz);
|
subghz);
|
||||||
// submenu_add_item(
|
// submenu_add_item(
|
||||||
// subghz->submenu, "Nero Sketch", SubmenuIndexNeroSketch, subghz_scene_set_type_submenu_callback, subghz);
|
// 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(
|
submenu_add_item(
|
||||||
subghz->submenu,
|
subghz->submenu,
|
||||||
"Gate TX_433",
|
"Gate TX_433",
|
||||||
@ -90,81 +95,86 @@ const bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event
|
|||||||
switch(event.event) {
|
switch(event.event) {
|
||||||
case SubmenuIndexPricenton:
|
case SubmenuIndexPricenton:
|
||||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "Princeton")) {
|
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
|
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;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexNiceFlo12bit:
|
case SubmenuIndexNiceFlo12bit:
|
||||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "Nice FLO")) {
|
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
|
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;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexNiceFlo24bit:
|
case SubmenuIndexNiceFlo24bit:
|
||||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "Nice FLO")) {
|
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
|
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;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexCAME12bit:
|
case SubmenuIndexCAME12bit:
|
||||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "CAME")) {
|
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
|
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;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexCAME24bit:
|
case SubmenuIndexCAME24bit:
|
||||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "CAME")) {
|
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
|
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;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// case SubmenuIndexNeroSketch:
|
// case SubmenuIndexNeroSketch:
|
||||||
// /* code */
|
// /* code */
|
||||||
// break;
|
// break;
|
||||||
|
// case SubmenuIndexNeroRadio:
|
||||||
|
// /* code */
|
||||||
|
// break;
|
||||||
case SubmenuIndexGateTX:
|
case SubmenuIndexGateTX:
|
||||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "GateTX")) {
|
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
|
key = (key & 0x00F0FFFF) | 0xF << 16; //btn 0xF, 0xC, 0xA, 0x6
|
||||||
subghz->protocol_result->code_last_found = subghz_protocol_common_reverse_key(
|
subghz->txrx->protocol_result->code_last_found =
|
||||||
key, subghz->protocol_result->code_last_count_bit);
|
subghz_protocol_common_reverse_key(
|
||||||
|
key, subghz->txrx->protocol_result->code_last_count_bit);
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexDoorHan:
|
case SubmenuIndexDoorHan:
|
||||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "KeeLoq")) {
|
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "KeeLoq")) {
|
||||||
subghz->protocol_result->code_last_count_bit = 64;
|
subghz->txrx->protocol_result->code_last_count_bit = 64;
|
||||||
subghz->protocol_result->serial = key & 0x0FFFFFFF;
|
subghz->txrx->protocol_result->serial = key & 0x0FFFFFFF;
|
||||||
subghz->protocol_result->btn = 0x2; //btn 0x1, 0x2, 0x4, 0x8
|
subghz->txrx->protocol_result->btn = 0x2; //btn 0x1, 0x2, 0x4, 0x8
|
||||||
subghz->protocol_result->cnt = 0x0003;
|
subghz->txrx->protocol_result->cnt = 0x0003;
|
||||||
if(subghz_protocol_keeloq_set_manufacture_name(
|
if(subghz_protocol_keeloq_set_manufacture_name(
|
||||||
subghz->protocol_result, "DoorHan")) {
|
subghz->txrx->protocol_result, "DoorHan")) {
|
||||||
subghz->protocol_result->code_last_found =
|
subghz->txrx->protocol_result->code_last_found =
|
||||||
subghz_protocol_keeloq_gen_key(subghz->protocol_result);
|
subghz_protocol_keeloq_gen_key(subghz->txrx->protocol_result);
|
||||||
generated_protocol = true;
|
generated_protocol = true;
|
||||||
} else {
|
} else {
|
||||||
generated_protocol = false;
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(generated_protocol) {
|
if(generated_protocol) {
|
||||||
subghz->frequency = subghz_frequencies[subghz_frequencies_433_92];
|
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
|
||||||
subghz->preset = FuriHalSubGhzPresetOok650Async;
|
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
|
||||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
|
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,26 @@
|
|||||||
|
|
||||||
#define SCENE_NO_MAN_CUSTOM_EVENT (11UL)
|
#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;
|
SubGhz* subghz = context;
|
||||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_NO_MAN_CUSTOM_EVENT);
|
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;
|
SubGhz* subghz = context;
|
||||||
|
|
||||||
// Setup view
|
// Setup view
|
||||||
Popup* popup = subghz->popup;
|
Popup* popup = subghz->popup;
|
||||||
popup_set_icon(popup, 32, 12, &I_DolphinFirstStart7_61x51);
|
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_timeout(popup, 1500);
|
||||||
popup_set_context(popup, subghz);
|
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);
|
popup_enable_timeout(popup);
|
||||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewPopup);
|
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;
|
SubGhz* subghz = context;
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SCENE_NO_MAN_CUSTOM_EVENT) {
|
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;
|
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;
|
SubGhz* subghz = context;
|
||||||
|
|
||||||
// Clear view
|
// Clear view
|
||||||
@ -45,4 +45,5 @@ const void subghz_scene_no_man_on_exit(void* context) {
|
|||||||
popup_set_context(popup, NULL);
|
popup_set_context(popup, NULL);
|
||||||
popup_set_timeout(popup, 0);
|
popup_set_timeout(popup, 0);
|
||||||
popup_disable_timeout(popup);
|
popup_disable_timeout(popup);
|
||||||
|
string_clean(subghz->error_str);
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include "../subghz_i.h"
|
#include "../subghz_i.h"
|
||||||
#include "../views/subghz_transmitter.h"
|
#include "../views/subghz_transmitter.h"
|
||||||
|
#include <lib/subghz/protocols/subghz_protocol_keeloq.h>
|
||||||
|
|
||||||
void subghz_scene_transmitter_callback(SubghzTransmitterEvent event, void* context) {
|
void subghz_scene_transmitter_callback(SubghzTransmitterEvent event, void* context) {
|
||||||
furi_assert(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);
|
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) {
|
const void subghz_scene_transmitter_on_enter(void* context) {
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
SubghzTransmitter* subghz_transmitter = subghz->subghz_transmitter;
|
subghz_transmitter_set_callback(
|
||||||
|
subghz->subghz_transmitter, subghz_scene_transmitter_callback, subghz);
|
||||||
subghz_transmitter_set_callback(subghz_transmitter, subghz_scene_transmitter_callback, subghz);
|
subghz_scene_transmitter_update_data_show(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->state_notifications = NOTIFICATION_IDLE_STATE;
|
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) {
|
const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubghzTransmitterEventSendStart) {
|
if(event.event == SubghzTransmitterEventSendStart) {
|
||||||
subghz->state_notifications = NOTIFICATION_TX_STATE;
|
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;
|
return true;
|
||||||
} else if(event.event == SubghzTransmitterEventSendStop) {
|
} else if(event.event == SubghzTransmitterEventSendStop) {
|
||||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||||
subghz_transmitter_tx_stop(subghz);
|
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||||
|
subghz_tx_stop(subghz);
|
||||||
subghz_sleep();
|
subghz_sleep();
|
||||||
|
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if(event.event == SubghzTransmitterEventBack) {
|
} else if(event.event == SubghzTransmitterEventBack) {
|
||||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||||
scene_manager_search_and_switch_to_previous_scene(
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
subghz->scene_manager, SubGhzSceneStart);
|
subghz->scene_manager, SubGhzSceneStart);
|
||||||
return true;
|
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) {
|
} else if(event.type == SceneManagerEventTypeTick) {
|
||||||
if(subghz->state_notifications == NOTIFICATION_TX_STATE) {
|
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) {
|
const void subghz_scene_transmitter_on_exit(void* context) {
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
SubghzTransmitter* subghz_transmitter = subghz->subghz_transmitter;
|
|
||||||
subghz_transmitter_set_callback(subghz_transmitter, NULL, subghz);
|
|
||||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
#include "subghz_i.h"
|
#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[] = {
|
const uint32_t subghz_frequencies[] = {
|
||||||
/* 300 - 348 */
|
/* 300 - 348 */
|
||||||
300000000,
|
300000000,
|
||||||
@ -20,7 +37,15 @@ const uint32_t subghz_frequencies[] = {
|
|||||||
928000000,
|
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_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;
|
const uint32_t subghz_frequencies_433_92 = 5;
|
||||||
|
|
||||||
bool subghz_custom_event_callback(void* context, uint32_t event) {
|
bool subghz_custom_event_callback(void* context, uint32_t event) {
|
||||||
@ -77,11 +102,6 @@ SubGhz* subghz_alloc() {
|
|||||||
SubGhzViewReceiver,
|
SubGhzViewReceiver,
|
||||||
subghz_receiver_get_view(subghz->subghz_receiver));
|
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
|
// Popup
|
||||||
subghz->popup = popup_alloc();
|
subghz->popup = popup_alloc();
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
@ -92,6 +112,11 @@ SubGhz* subghz_alloc() {
|
|||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
subghz->view_dispatcher, SubGhzViewTextInput, text_input_get_view(subghz->text_input));
|
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
|
// Transmitter
|
||||||
subghz->subghz_transmitter = subghz_transmitter_alloc();
|
subghz->subghz_transmitter = subghz_transmitter_alloc();
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
@ -99,6 +124,13 @@ SubGhz* subghz_alloc() {
|
|||||||
SubGhzViewTransmitter,
|
SubGhzViewTransmitter,
|
||||||
subghz_transmitter_get_view(subghz->subghz_transmitter));
|
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
|
// Carrier Test Module
|
||||||
subghz->subghz_test_carrier = subghz_test_carrier_alloc();
|
subghz->subghz_test_carrier = subghz_test_carrier_alloc();
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
@ -120,17 +152,26 @@ SubGhz* subghz_alloc() {
|
|||||||
SubGhzViewStatic,
|
SubGhzViewStatic,
|
||||||
subghz_test_static_get_view(subghz->subghz_test_static));
|
subghz_test_static_get_view(subghz->subghz_test_static));
|
||||||
|
|
||||||
//init Worker & Protocol
|
//init Worker & Protocol & History
|
||||||
subghz->worker = subghz_worker_alloc();
|
subghz->txrx = furi_alloc(sizeof(SubGhzTxRx));
|
||||||
subghz->protocol = subghz_protocol_alloc();
|
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_set_overrun_callback(
|
||||||
subghz->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset);
|
subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset);
|
||||||
subghz_worker_set_pair_callback(
|
subghz_worker_set_pair_callback(
|
||||||
subghz->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse);
|
subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse);
|
||||||
subghz_worker_set_context(subghz->worker, subghz->protocol);
|
subghz_worker_set_context(subghz->txrx->worker, subghz->txrx->protocol);
|
||||||
|
|
||||||
subghz_protocol_load_keeloq_file(subghz->protocol, "/ext/subghz/keeloq_mfcodes");
|
//Init Error_str
|
||||||
subghz_protocol_load_nice_flor_s_file(subghz->protocol, "/ext/subghz/nice_floor_s_rx");
|
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);
|
//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);
|
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTextInput);
|
||||||
text_input_free(subghz->text_input);
|
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);
|
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTransmitter);
|
||||||
subghz_transmitter_free(subghz->subghz_transmitter);
|
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
|
// Submenu
|
||||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewMenu);
|
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewMenu);
|
||||||
submenu_free(subghz->submenu);
|
submenu_free(subghz->submenu);
|
||||||
|
|
||||||
// DialogEx
|
|
||||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewDialogEx);
|
|
||||||
dialog_ex_free(subghz->dialog_ex);
|
|
||||||
|
|
||||||
// Popup
|
// Popup
|
||||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewPopup);
|
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewPopup);
|
||||||
popup_free(subghz->popup);
|
popup_free(subghz->popup);
|
||||||
@ -186,9 +231,14 @@ void subghz_free(SubGhz* subghz) {
|
|||||||
furi_record_close("gui");
|
furi_record_close("gui");
|
||||||
subghz->gui = NULL;
|
subghz->gui = NULL;
|
||||||
|
|
||||||
//Worker & Protocol
|
//Worker & Protocol & History
|
||||||
subghz_protocol_free(subghz->protocol);
|
subghz_protocol_free(subghz->txrx->protocol);
|
||||||
subghz_worker_free(subghz->worker);
|
subghz_worker_free(subghz->txrx->worker);
|
||||||
|
subghz_history_free(subghz->txrx->history);
|
||||||
|
free(subghz->txrx);
|
||||||
|
|
||||||
|
//Error string
|
||||||
|
string_clear(subghz->error_str);
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
furi_record_close("notification");
|
furi_record_close("notification");
|
||||||
|
@ -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(instance);
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhzProtocolCommon* protocol = 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)) &&
|
if((instance->code_last_found == (protocol->code_last_found & 0xFFFF0FFFFFFFFFFF)) &&
|
||||||
((millis() - instance->last_update_timestamp) < 500)) {
|
((millis() - instance->last_update_timestamp) < 500)) {
|
||||||
instance->last_update_timestamp = millis();
|
instance->last_update_timestamp = millis();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->code_last_found = protocol->code_last_found & 0xFFFF0FFFFFFFFFFF;
|
instance->code_last_found = protocol->code_last_found & 0xFFFF0FFFFFFFFFFF;
|
||||||
instance->last_update_timestamp = millis();
|
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].te = 0;
|
||||||
instance->history[instance->last_index_write].manufacture_name = NULL;
|
instance->history[instance->last_index_write].manufacture_name = NULL;
|
||||||
instance->history[instance->last_index_write].name = protocol->name;
|
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->history[instance->last_index_write].type_protocol = protocol->type_protocol;
|
||||||
|
|
||||||
instance->last_index_write++;
|
instance->last_index_write++;
|
||||||
|
return true;
|
||||||
}
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
||||||
@ -94,8 +95,15 @@ bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output
|
|||||||
*
|
*
|
||||||
* @param instance - SubGhzHistory instance
|
* @param instance - SubGhzHistory instance
|
||||||
* @param context - SubGhzProtocolCommon context
|
* @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
|
/** 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*
|
* @return SubGhzProtocolCommonLoad*
|
||||||
*/
|
*/
|
||||||
SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
|
SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
|
||||||
|
|
||||||
|
void subghz_hopper_update(void* context);
|
||||||
|
@ -19,6 +19,9 @@ void subghz_begin(FuriHalSubGhzPreset preset) {
|
|||||||
|
|
||||||
uint32_t subghz_rx(void* context, uint32_t frequency) {
|
uint32_t subghz_rx(void* context, uint32_t frequency) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
|
||||||
|
furi_check(0);
|
||||||
|
}
|
||||||
SubGhzWorker* worker = context;
|
SubGhzWorker* worker = context;
|
||||||
|
|
||||||
furi_hal_subghz_idle();
|
furi_hal_subghz_idle();
|
||||||
@ -33,6 +36,9 @@ uint32_t subghz_rx(void* context, uint32_t frequency) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t subghz_tx(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();
|
furi_hal_subghz_idle();
|
||||||
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
|
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
|
||||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||||
@ -53,6 +59,7 @@ void subghz_rx_end(void* context) {
|
|||||||
subghz_worker_stop(worker);
|
subghz_worker_stop(worker);
|
||||||
furi_hal_subghz_stop_async_rx();
|
furi_hal_subghz_stop_async_rx();
|
||||||
}
|
}
|
||||||
|
furi_hal_subghz_idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_sleep(void) {
|
void subghz_sleep(void) {
|
||||||
@ -66,41 +73,46 @@ void subghz_frequency_preset_to_str(void* context, string_t output) {
|
|||||||
output,
|
output,
|
||||||
"Frequency: %d\n"
|
"Frequency: %d\n"
|
||||||
"Preset: %d\n",
|
"Preset: %d\n",
|
||||||
(int)subghz->frequency,
|
(int)subghz->txrx->frequency,
|
||||||
(int)subghz->preset);
|
(int)subghz->txrx->preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_transmitter_tx_start(void* context) {
|
void subghz_tx_start(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
subghz->encoder = subghz_protocol_encoder_common_alloc();
|
subghz->txrx->encoder = subghz_protocol_encoder_common_alloc();
|
||||||
subghz->encoder->repeat = 200; //max repeat with the button held down
|
subghz->txrx->encoder->repeat = 200; //max repeat with the button held down
|
||||||
//get upload
|
//get upload
|
||||||
if(subghz->protocol_result->get_upload_protocol) {
|
if(subghz->txrx->protocol_result->get_upload_protocol) {
|
||||||
if(subghz->protocol_result->get_upload_protocol(subghz->protocol_result, subghz->encoder)) {
|
if(subghz->txrx->protocol_result->get_upload_protocol(
|
||||||
if(subghz->preset) {
|
subghz->txrx->protocol_result, subghz->txrx->encoder)) {
|
||||||
subghz_begin(subghz->preset);
|
if(subghz->txrx->preset) {
|
||||||
|
subghz_begin(subghz->txrx->preset);
|
||||||
} else {
|
} else {
|
||||||
subghz_begin(FuriHalSubGhzPresetOok650Async);
|
subghz_begin(FuriHalSubGhzPresetOok270Async);
|
||||||
}
|
}
|
||||||
if(subghz->frequency) {
|
if(subghz->txrx->frequency) {
|
||||||
subghz_tx(subghz->frequency);
|
subghz_tx(subghz->txrx->frequency);
|
||||||
} else {
|
} else {
|
||||||
subghz_tx(433920000);
|
subghz_tx(433920000);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Start TX
|
//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;
|
SubGhz* subghz = context;
|
||||||
//Stop TX
|
//Stop TX
|
||||||
furi_hal_subghz_stop_async_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 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);
|
subghz_save_protocol_to_file(subghz, subghz->text_store);
|
||||||
}
|
}
|
||||||
notification_message(subghz->notifications, &sequence_reset_red);
|
notification_message(subghz->notifications, &sequence_reset_red);
|
||||||
@ -133,7 +145,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
|||||||
if(res != 1) {
|
if(res != 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
subghz->frequency = (uint32_t)data;
|
subghz->txrx->frequency = (uint32_t)data;
|
||||||
|
|
||||||
// Read and parse preset from 2st line
|
// Read and parse preset from 2st line
|
||||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
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) {
|
if(res != 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
subghz->preset = (FuriHalSubGhzPreset)data;
|
subghz->txrx->preset = (FuriHalSubGhzPreset)data;
|
||||||
|
|
||||||
// Read and parse name protocol from 2st line
|
// Read and parse name protocol from 2st line
|
||||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
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
|
// strlen("Protocol: ") = 10
|
||||||
string_right(temp_str, 10);
|
string_right(temp_str, 10);
|
||||||
subghz->protocol_result =
|
subghz->txrx->protocol_result =
|
||||||
subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str));
|
subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str));
|
||||||
if(subghz->protocol_result == NULL) {
|
if(subghz->txrx->protocol_result == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!subghz->protocol_result->to_load_protocol_from_file(
|
if(!subghz->txrx->protocol_result->to_load_protocol_from_file(
|
||||||
file_worker, subghz->protocol_result)) {
|
file_worker, subghz->txrx->protocol_result)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
loaded = true;
|
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) {
|
bool subghz_save_protocol_to_file(void* context, const char* dev_name) {
|
||||||
|
furi_assert(context);
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
furi_assert(subghz->protocol_result);
|
furi_assert(subghz->txrx->protocol_result);
|
||||||
FileWorker* file_worker = file_worker_alloc(false);
|
FileWorker* file_worker = file_worker_alloc(false);
|
||||||
string_t dev_file_name;
|
string_t dev_file_name;
|
||||||
string_init(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;
|
break;
|
||||||
}
|
}
|
||||||
//Get string save
|
//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
|
// Prepare and write data to file
|
||||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) {
|
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) {
|
||||||
break;
|
break;
|
||||||
@ -276,7 +289,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) {
|
|||||||
if(sscanf_res != 1) {
|
if(sscanf_res != 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
subghz->frequency = (uint32_t)data;
|
subghz->txrx->frequency = (uint32_t)data;
|
||||||
|
|
||||||
// Read and parse preset from 2st line
|
// Read and parse preset from 2st line
|
||||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
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) {
|
if(sscanf_res != 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
subghz->preset = (FuriHalSubGhzPreset)data;
|
subghz->txrx->preset = (FuriHalSubGhzPreset)data;
|
||||||
|
|
||||||
// Read and parse name protocol from 3st line
|
// Read and parse name protocol from 3st line
|
||||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
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
|
// strlen("Protocol: ") = 10
|
||||||
string_right(temp_str, 10);
|
string_right(temp_str, 10);
|
||||||
subghz->protocol_result =
|
subghz->txrx->protocol_result =
|
||||||
subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str));
|
subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str));
|
||||||
if(subghz->protocol_result == NULL) {
|
if(subghz->txrx->protocol_result == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!subghz->protocol_result->to_load_protocol_from_file(
|
if(!subghz->txrx->protocol_result->to_load_protocol_from_file(
|
||||||
file_worker, subghz->protocol_result)) {
|
file_worker, subghz->txrx->protocol_result)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
res = true;
|
res = true;
|
||||||
@ -328,3 +341,57 @@ uint32_t subghz_random_serial(void) {
|
|||||||
}
|
}
|
||||||
return (uint32_t)rand();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
#include <notification/notification-messages.h>
|
#include <notification/notification-messages.h>
|
||||||
#include <gui/view_dispatcher.h>
|
#include <gui/view_dispatcher.h>
|
||||||
#include <gui/modules/submenu.h>
|
#include <gui/modules/submenu.h>
|
||||||
#include <gui/modules/dialog_ex.h>
|
|
||||||
#include <gui/modules/popup.h>
|
#include <gui/modules/popup.h>
|
||||||
#include <gui/modules/text_input.h>
|
#include <gui/modules/text_input.h>
|
||||||
|
#include <gui/modules/widget.h>
|
||||||
|
|
||||||
#include <subghz/scenes/subghz_scene.h>
|
#include <subghz/scenes/subghz_scene.h>
|
||||||
|
|
||||||
@ -26,6 +26,8 @@
|
|||||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
||||||
#include "subghz_history.h"
|
#include "subghz_history.h"
|
||||||
|
|
||||||
|
#include <gui/modules/variable-item-list.h>
|
||||||
|
|
||||||
#define SUBGHZ_TEXT_STORE_SIZE 128
|
#define SUBGHZ_TEXT_STORE_SIZE 128
|
||||||
|
|
||||||
#define NOTIFICATION_STARTING_STATE 0u
|
#define NOTIFICATION_STARTING_STATE 0u
|
||||||
@ -33,48 +35,81 @@
|
|||||||
#define NOTIFICATION_TX_STATE 2u
|
#define NOTIFICATION_TX_STATE 2u
|
||||||
#define NOTIFICATION_RX_STATE 3u
|
#define NOTIFICATION_RX_STATE 3u
|
||||||
|
|
||||||
|
extern const char* const subghz_frequencies_text[];
|
||||||
extern const uint32_t subghz_frequencies[];
|
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_frequencies_count;
|
||||||
|
extern const uint32_t subghz_hopper_frequencies_count;
|
||||||
extern const uint32_t subghz_frequencies_433_92;
|
extern const uint32_t subghz_frequencies_433_92;
|
||||||
|
|
||||||
struct SubGhz {
|
/** SubGhzTxRx state */
|
||||||
Gui* gui;
|
typedef enum {
|
||||||
NotificationApp* notifications;
|
SubGhzTxRxStateIdle,
|
||||||
|
SubGhzTxRxStateRx,
|
||||||
|
SubGhzTxRxStateTx,
|
||||||
|
} SubGhzTxRxState;
|
||||||
|
|
||||||
|
/** SubGhzHopperState state */
|
||||||
|
typedef enum {
|
||||||
|
SubGhzHopperStateOFF,
|
||||||
|
SubGhzHopperStateRunnig,
|
||||||
|
SubGhzHopperStatePause,
|
||||||
|
SubGhzHopperStateRSSITimeOut,
|
||||||
|
} SubGhzHopperState;
|
||||||
|
|
||||||
|
struct SubGhzTxRx {
|
||||||
SubGhzWorker* worker;
|
SubGhzWorker* worker;
|
||||||
SubGhzProtocol* protocol;
|
SubGhzProtocol* protocol;
|
||||||
SubGhzProtocolCommon* protocol_result;
|
SubGhzProtocolCommon* protocol_result;
|
||||||
SubGhzProtocolCommonEncoder* encoder;
|
SubGhzProtocolCommonEncoder* encoder;
|
||||||
uint32_t frequency;
|
uint32_t frequency;
|
||||||
FuriHalSubGhzPreset preset;
|
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;
|
SceneManager* scene_manager;
|
||||||
ViewDispatcher* view_dispatcher;
|
ViewDispatcher* view_dispatcher;
|
||||||
|
|
||||||
Submenu* submenu;
|
Submenu* submenu;
|
||||||
DialogEx* dialog_ex;
|
|
||||||
Popup* popup;
|
Popup* popup;
|
||||||
TextInput* text_input;
|
TextInput* text_input;
|
||||||
|
Widget* widget;
|
||||||
char text_store[SUBGHZ_TEXT_STORE_SIZE + 1];
|
char text_store[SUBGHZ_TEXT_STORE_SIZE + 1];
|
||||||
uint8_t state_notifications;
|
uint8_t state_notifications;
|
||||||
|
|
||||||
SubghzReceiver* subghz_receiver;
|
SubghzReceiver* subghz_receiver;
|
||||||
SubghzTransmitter* subghz_transmitter;
|
SubghzTransmitter* subghz_transmitter;
|
||||||
|
VariableItemList* variable_item_list;
|
||||||
|
|
||||||
SubghzTestStatic* subghz_test_static;
|
SubghzTestStatic* subghz_test_static;
|
||||||
SubghzTestCarrier* subghz_test_carrier;
|
SubghzTestCarrier* subghz_test_carrier;
|
||||||
SubghzTestPacket* subghz_test_packet;
|
SubghzTestPacket* subghz_test_packet;
|
||||||
|
string_t error_str;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SubGhzViewMenu,
|
SubGhzViewMenu,
|
||||||
|
|
||||||
SubGhzViewDialogEx,
|
|
||||||
SubGhzViewReceiver,
|
SubGhzViewReceiver,
|
||||||
SubGhzViewPopup,
|
SubGhzViewPopup,
|
||||||
SubGhzViewTextInput,
|
SubGhzViewTextInput,
|
||||||
|
SubGhzViewWidget,
|
||||||
SubGhzViewTransmitter,
|
SubGhzViewTransmitter,
|
||||||
|
SubGhzViewVariableItemList,
|
||||||
SubGhzViewStatic,
|
SubGhzViewStatic,
|
||||||
SubGhzViewTestCarrier,
|
SubGhzViewTestCarrier,
|
||||||
SubGhzViewTestPacket,
|
SubGhzViewTestPacket,
|
||||||
@ -86,8 +121,8 @@ uint32_t subghz_tx(uint32_t frequency);
|
|||||||
void subghz_idle(void);
|
void subghz_idle(void);
|
||||||
void subghz_rx_end(void* context);
|
void subghz_rx_end(void* context);
|
||||||
void subghz_sleep(void);
|
void subghz_sleep(void);
|
||||||
void subghz_transmitter_tx_start(void* context);
|
void subghz_tx_start(void* context);
|
||||||
void subghz_transmitter_tx_stop(void* context);
|
void subghz_tx_stop(void* context);
|
||||||
bool subghz_key_load(SubGhz* subghz, const char* file_path);
|
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(void* context, const char* dev_name);
|
||||||
bool subghz_load_protocol_from_file(SubGhz* subghz);
|
bool subghz_load_protocol_from_file(SubGhz* subghz);
|
||||||
|
@ -1,42 +1,32 @@
|
|||||||
#include "subghz_receiver.h"
|
#include "subghz_receiver.h"
|
||||||
#include "../subghz_i.h"
|
#include "../subghz_i.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <furi.h>
|
|
||||||
#include <furi-hal.h>
|
|
||||||
#include <input/input.h>
|
#include <input/input.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <notification/notification-messages.h>
|
|
||||||
#include <lib/subghz/protocols/subghz_protocol_princeton.h>
|
|
||||||
|
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
|
#include <m-string.h>
|
||||||
|
#include <m-array.h>
|
||||||
|
|
||||||
#define FRAME_HEIGHT 12
|
#define FRAME_HEIGHT 12
|
||||||
#define MAX_LEN_PX 100
|
#define MAX_LEN_PX 100
|
||||||
#define MENU_ITEMS 4
|
#define MENU_ITEMS 4
|
||||||
|
|
||||||
#define COUNT_FREQUNCY_HOPPER 3
|
typedef struct {
|
||||||
const uint32_t subghz_frequencies_hopper[] = {
|
string_t item_str;
|
||||||
/* 300 - 348 */
|
uint8_t type;
|
||||||
315000000,
|
} SubGhzReceiverMenuItem;
|
||||||
/* 387 - 464 */
|
|
||||||
433920000, /* LPD433 mid */
|
ARRAY_DEF(SubGhzReceiverMenuItemArray, SubGhzReceiverMenuItem, M_POD_OPLIST)
|
||||||
/* 779 - 928 */
|
|
||||||
868350000,
|
#define M_OPL_SubGhzReceiverMenuItemArray_t() \
|
||||||
|
ARRAY_OPLIST(SubGhzReceiverMenuItemArray, M_POD_OPLIST)
|
||||||
|
|
||||||
|
struct SubGhzReceiverHistory {
|
||||||
|
SubGhzReceiverMenuItemArray_t data;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef struct SubGhzReceiverHistory SubGhzReceiverHistory;
|
||||||
ReceiverSceneStart,
|
|
||||||
ReceiverSceneMain,
|
|
||||||
ReceiverSceneConfig,
|
|
||||||
ReceiverSceneInfo,
|
|
||||||
} SubghzReceiverScene;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SubGhzHopperStateOFF,
|
|
||||||
SubGhzHopperStatePause,
|
|
||||||
SubGhzHopperStateRunnig,
|
|
||||||
SubGhzHopperStateRSSITimeOut,
|
|
||||||
} SubGhzHopperState;
|
|
||||||
|
|
||||||
static const Icon* ReceiverItemIcons[] = {
|
static const Icon* ReceiverItemIcons[] = {
|
||||||
[TYPE_PROTOCOL_UNKNOWN] = &I_Quest_7x8,
|
[TYPE_PROTOCOL_UNKNOWN] = &I_Quest_7x8,
|
||||||
@ -48,27 +38,16 @@ struct SubghzReceiver {
|
|||||||
View* view;
|
View* view;
|
||||||
SubghzReceiverCallback callback;
|
SubghzReceiverCallback callback;
|
||||||
void* context;
|
void* context;
|
||||||
SubGhzWorker* worker;
|
|
||||||
SubGhzProtocol* protocol;
|
|
||||||
osTimerId timer;
|
|
||||||
SubGhzHopperState hopper_state;
|
|
||||||
uint8_t hopper_timeout;
|
|
||||||
uint32_t event_key_sequence;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
string_t text;
|
string_t frequency_str;
|
||||||
uint16_t scene;
|
string_t preset_str;
|
||||||
SubGhzProtocolCommon* protocol_result;
|
string_t history_stat_str;
|
||||||
SubGhzHistory* history;
|
SubGhzReceiverHistory* history;
|
||||||
uint8_t frequency;
|
|
||||||
uint8_t temp_frequency;
|
|
||||||
uint32_t real_frequency;
|
|
||||||
|
|
||||||
uint16_t idx;
|
uint16_t idx;
|
||||||
uint16_t list_offset;
|
uint16_t list_offset;
|
||||||
uint16_t history_item;
|
uint16_t history_item;
|
||||||
bool menu;
|
|
||||||
} SubghzReceiverModel;
|
} SubghzReceiverModel;
|
||||||
|
|
||||||
void subghz_receiver_set_callback(
|
void subghz_receiver_set_callback(
|
||||||
@ -81,35 +60,6 @@ void subghz_receiver_set_callback(
|
|||||||
subghz_receiver->context = context;
|
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) {
|
static void subghz_receiver_update_offset(SubghzReceiver* subghz_receiver) {
|
||||||
furi_assert(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) {
|
static void subghz_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT);
|
canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT);
|
||||||
@ -144,163 +126,56 @@ static void subghz_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scroll
|
|||||||
}
|
}
|
||||||
|
|
||||||
void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
|
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_clear(canvas);
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
|
||||||
|
elements_button_left(canvas, "Config");
|
||||||
|
|
||||||
|
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_draw_line(canvas, 46, 51, 125, 51);
|
||||||
|
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;
|
||||||
|
|
||||||
switch(model->scene) {
|
|
||||||
case ReceiverSceneMain:
|
|
||||||
for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) {
|
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);
|
size_t idx = CLAMP(i + model->list_offset, model->history_item, 0);
|
||||||
subghz_history_get_text_item_menu(model->history, str_buff, idx);
|
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);
|
elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX);
|
||||||
if(model->idx == idx) {
|
if(model->idx == idx) {
|
||||||
subghz_receiver_draw_frame(canvas, i, scrollbar);
|
subghz_receiver_draw_frame(canvas, i, scrollbar);
|
||||||
} else {
|
} else {
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
}
|
}
|
||||||
canvas_draw_icon(
|
canvas_draw_icon(canvas, 1, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]);
|
||||||
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));
|
canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, string_get_cstr(str_buff));
|
||||||
string_clean(str_buff);
|
string_clean(str_buff);
|
||||||
}
|
}
|
||||||
if(scrollbar) {
|
if(scrollbar) {
|
||||||
elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item);
|
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");
|
|
||||||
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_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: <OFF>");
|
|
||||||
} else {
|
|
||||||
canvas_draw_str(canvas, 0, 8, "Frequency: < --- >");
|
|
||||||
canvas_draw_str(canvas, 0, 18, "Frequency Hopping: <ON>");
|
|
||||||
}
|
|
||||||
canvas_draw_str(canvas, 0, 28, "Modulation: <AM>");
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_clear(str_buff);
|
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) {
|
bool subghz_receiver_input(InputEvent* event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|
||||||
uint8_t scene = 0;
|
|
||||||
SubghzReceiver* subghz_receiver = context;
|
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) {
|
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||||
with_view_model(
|
subghz_receiver->callback(SubghzReceverEventBack, subghz_receiver->context);
|
||||||
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(
|
} else if(
|
||||||
event->key == InputKeyUp &&
|
event->key == InputKeyUp &&
|
||||||
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
||||||
@ -314,292 +189,50 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
|
|||||||
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||||
if(model->idx != subghz_history_get_item(model->history) - 1) model->idx++;
|
if(model->idx != model->history_item - 1) model->idx++;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
} 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);
|
subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context);
|
||||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||||
subghz_receiver->event_key_sequence = event->sequence;
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||||
string_clean(model->text);
|
if(model->history_item != 0) {
|
||||||
model->protocol_result = subghz_protocol_get_by_name(
|
subghz_receiver->callback(SubghzReceverEventOK, subghz_receiver->context);
|
||||||
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:
|
|
||||||
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;
|
return false;
|
||||||
});
|
});
|
||||||
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);
|
subghz_receiver_update_offset(subghz_receiver);
|
||||||
if(scene != ReceiverSceneInfo) {
|
|
||||||
with_view_model(
|
|
||||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
|
||||||
if(subghz_history_get_text_space_left(model->history, NULL)) {
|
|
||||||
subghz_receiver_history_full(subghz_receiver);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
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) {
|
void subghz_receiver_enter(void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubghzReceiver* subghz_receiver = 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_receiver_exit(void* context) {
|
void subghz_receiver_exit(void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubghzReceiver* subghz_receiver = context;
|
SubghzReceiver* subghz_receiver = context;
|
||||||
osTimerStop(subghz_receiver->timer);
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||||
string_clean(model->text);
|
string_clean(model->frequency_str);
|
||||||
return true;
|
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() {
|
SubghzReceiver* subghz_receiver_alloc() {
|
||||||
@ -616,14 +249,14 @@ SubghzReceiver* subghz_receiver_alloc() {
|
|||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||||
string_init(model->text);
|
string_init(model->frequency_str);
|
||||||
model->history = subghz_history_alloc();
|
string_init(model->preset_str);
|
||||||
|
string_init(model->history_stat_str);
|
||||||
|
model->history = furi_alloc(sizeof(SubGhzReceiverHistory));
|
||||||
|
SubGhzReceiverMenuItemArray_init(model->history->data);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
subghz_receiver->timer =
|
|
||||||
osTimerNew(subghz_receiver_timer_callback, osTimerPeriodic, subghz_receiver, NULL);
|
|
||||||
subghz_receiver->hopper_state = SubGhzHopperStateOFF;
|
|
||||||
return subghz_receiver;
|
return subghz_receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,11 +265,18 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver) {
|
|||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||||
string_clear(model->text);
|
string_clear(model->frequency_str);
|
||||||
subghz_history_free(model->history);
|
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;
|
return false;
|
||||||
});
|
});
|
||||||
osTimerDelete(subghz_receiver->timer);
|
|
||||||
view_free(subghz_receiver->view);
|
view_free(subghz_receiver->view);
|
||||||
free(subghz_receiver);
|
free(subghz_receiver);
|
||||||
}
|
}
|
||||||
@ -646,43 +286,24 @@ View* subghz_receiver_get_view(SubghzReceiver* subghz_receiver) {
|
|||||||
return subghz_receiver->view;
|
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);
|
furi_assert(subghz_receiver);
|
||||||
uint32_t frequency;
|
uint32_t idx = 0;
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||||
frequency = subghz_history_get_frequency(model->history, model->idx);
|
idx = model->idx;
|
||||||
return false;
|
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);
|
furi_assert(subghz_receiver);
|
||||||
FuriHalSubGhzPreset preset;
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||||
preset = subghz_history_get_preset(model->history, model->idx);
|
model->idx = idx;
|
||||||
return false;
|
if(model->idx > 2) model->list_offset = idx - 2;
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
return preset;
|
subghz_receiver_update_offset(subghz_receiver);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
@ -1,21 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
|
||||||
#include <lib/subghz/protocols/subghz_protocol.h>
|
|
||||||
#include <lib/subghz/subghz_worker.h>
|
|
||||||
#include "../subghz_history.h"
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SubghzReceverEventOK,
|
SubghzReceverEventOK,
|
||||||
SubghzReceverEventConfig,
|
SubghzReceverEventConfig,
|
||||||
SubghzReceverEventMain,
|
|
||||||
SubghzReceverEventSave,
|
|
||||||
SubghzReceverEventBack,
|
SubghzReceverEventBack,
|
||||||
SubghzReceverEventMore,
|
|
||||||
SubghzReceverEventSendStart,
|
|
||||||
SubghzReceverEventSendStop,
|
|
||||||
SubghzReceverEventSendHistoryFull,
|
|
||||||
} SubghzReceverEvent;
|
} SubghzReceverEvent;
|
||||||
|
|
||||||
typedef struct SubghzReceiver SubghzReceiver;
|
typedef struct SubghzReceiver SubghzReceiver;
|
||||||
@ -33,17 +23,19 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver);
|
|||||||
|
|
||||||
View* subghz_receiver_get_view(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,
|
SubghzReceiver* subghz_receiver,
|
||||||
SubGhzProtocolCommon* protocol_result,
|
const char* frequency_str,
|
||||||
SubGhzProtocol* protocol);
|
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_exit(void* context);
|
||||||
|
|
||||||
void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output);
|
|
@ -1,13 +1,8 @@
|
|||||||
#include "subghz_transmitter.h"
|
#include "subghz_transmitter.h"
|
||||||
#include "../subghz_i.h"
|
#include "../subghz_i.h"
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <furi.h>
|
|
||||||
#include <furi-hal.h>
|
|
||||||
#include <input/input.h>
|
#include <input/input.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <notification/notification-messages.h>
|
|
||||||
#include <lib/subghz/protocols/subghz_protocol_keeloq.h>
|
|
||||||
|
|
||||||
struct SubghzTransmitter {
|
struct SubghzTransmitter {
|
||||||
View* view;
|
View* view;
|
||||||
@ -16,11 +11,10 @@ struct SubghzTransmitter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
string_t text;
|
string_t frequency_str;
|
||||||
uint16_t scene;
|
string_t preset_str;
|
||||||
uint32_t real_frequency;
|
string_t key_str;
|
||||||
FuriHalSubGhzPreset preset;
|
uint8_t show_button;
|
||||||
SubGhzProtocolCommon* protocol;
|
|
||||||
} SubghzTransmitterModel;
|
} SubghzTransmitterModel;
|
||||||
|
|
||||||
void subghz_transmitter_set_callback(
|
void subghz_transmitter_set_callback(
|
||||||
@ -33,24 +27,19 @@ void subghz_transmitter_set_callback(
|
|||||||
subghz_transmitter->context = context;
|
subghz_transmitter->context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_transmitter_set_protocol(
|
void subghz_transmitter_add_data_to_show(
|
||||||
SubghzTransmitter* subghz_transmitter,
|
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(
|
with_view_model(
|
||||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||||
model->protocol = protocol;
|
string_set(model->key_str, key_str);
|
||||||
return true;
|
string_set(model->frequency_str, frequency_str);
|
||||||
});
|
string_set(model->preset_str, preset_str);
|
||||||
}
|
model->show_button = show_button;
|
||||||
|
|
||||||
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;
|
|
||||||
return true;
|
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) {
|
void subghz_transmitter_draw(Canvas* canvas, SubghzTransmitterModel* model) {
|
||||||
char buffer[64];
|
|
||||||
canvas_clear(canvas);
|
canvas_clear(canvas);
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
elements_multiline_text(canvas, 0, 8, string_get_cstr(model->text));
|
elements_multiline_text(canvas, 0, 8, string_get_cstr(model->key_str));
|
||||||
snprintf(
|
canvas_draw_str(canvas, 78, 8, string_get_cstr(model->frequency_str));
|
||||||
buffer,
|
canvas_draw_str(canvas, 113, 8, string_get_cstr(model->preset_str));
|
||||||
sizeof(buffer),
|
if(model->show_button) subghz_transmitter_button_right(canvas, "Send");
|
||||||
"%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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subghz_transmitter_input(InputEvent* event, void* context) {
|
bool subghz_transmitter_input(InputEvent* event, void* context) {
|
||||||
@ -114,26 +90,25 @@ bool subghz_transmitter_input(InputEvent* event, void* context) {
|
|||||||
SubghzTransmitter* subghz_transmitter = context;
|
SubghzTransmitter* subghz_transmitter = context;
|
||||||
bool can_be_sent = false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||||
if(model->protocol && model->protocol->get_upload_protocol) {
|
if(model->show_button) {
|
||||||
if((!strcmp(model->protocol->name, "KeeLoq")) &&
|
|
||||||
(!strcmp(
|
|
||||||
subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
can_be_sent = true;
|
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;
|
return true;
|
||||||
});
|
});
|
||||||
//if(event->type != InputTypeShort) return false;
|
|
||||||
|
|
||||||
if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) {
|
if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) {
|
||||||
subghz_transmitter->callback(SubghzTransmitterEventSendStart, subghz_transmitter->context);
|
subghz_transmitter->callback(SubghzTransmitterEventSendStart, subghz_transmitter->context);
|
||||||
@ -146,37 +121,14 @@ bool subghz_transmitter_input(InputEvent* event, void* context) {
|
|||||||
return true;
|
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) {
|
void subghz_transmitter_enter(void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubghzTransmitter* subghz_transmitter = 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;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_transmitter_exit(void* context) {
|
void subghz_transmitter_exit(void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubghzTransmitter* subghz_transmitter = context;
|
// SubghzTransmitter* subghz_transmitter = context;
|
||||||
with_view_model(
|
|
||||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
|
||||||
string_clean(model->text);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SubghzTransmitter* subghz_transmitter_alloc() {
|
SubghzTransmitter* subghz_transmitter_alloc() {
|
||||||
@ -194,7 +146,9 @@ SubghzTransmitter* subghz_transmitter_alloc() {
|
|||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_transmitter->view, (SubghzTransmitterModel * 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 true;
|
||||||
});
|
});
|
||||||
return subghz_transmitter;
|
return subghz_transmitter;
|
||||||
@ -205,7 +159,9 @@ void subghz_transmitter_free(SubghzTransmitter* subghz_transmitter) {
|
|||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_transmitter->view, (SubghzTransmitterModel * 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;
|
return true;
|
||||||
});
|
});
|
||||||
view_free(subghz_transmitter->view);
|
view_free(subghz_transmitter->view);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SubghzTransmitterEventSendStart,
|
SubghzTransmitterEventSendStart,
|
||||||
@ -25,10 +24,9 @@ void subghz_transmitter_free(SubghzTransmitter* subghz_transmitter);
|
|||||||
|
|
||||||
View* subghz_transmitter_get_view(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,
|
SubghzTransmitter* subghz_transmitter,
|
||||||
SubGhzProtocolCommon* protocol);
|
const char* key_str,
|
||||||
void subghz_transmitter_set_frequency_preset(
|
const char* frequency_str,
|
||||||
SubghzTransmitter* subghz_transmitter,
|
const char* preset_str,
|
||||||
uint32_t frequency,
|
uint8_t show_button);
|
||||||
FuriHalSubGhzPreset preset);
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "subghz_protocol_faac_slh.h"
|
#include "subghz_protocol_faac_slh.h"
|
||||||
#include "subghz_protocol_nero_sketch.h"
|
#include "subghz_protocol_nero_sketch.h"
|
||||||
#include "subghz_protocol_star_line.h"
|
#include "subghz_protocol_star_line.h"
|
||||||
|
#include "subghz_protocol_nero_radio.h"
|
||||||
|
|
||||||
#include "../subghz_keystore.h"
|
#include "../subghz_keystore.h"
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ typedef enum {
|
|||||||
SubGhzProtocolTypeFaacSLH,
|
SubGhzProtocolTypeFaacSLH,
|
||||||
SubGhzProtocolTypeNeroSketch,
|
SubGhzProtocolTypeNeroSketch,
|
||||||
SubGhzProtocolTypeStarLine,
|
SubGhzProtocolTypeStarLine,
|
||||||
|
SubGhzProtocolTypeNeroRadio,
|
||||||
|
|
||||||
SubGhzProtocolTypeMax,
|
SubGhzProtocolTypeMax,
|
||||||
} SubGhzProtocolType;
|
} SubGhzProtocolType;
|
||||||
@ -88,6 +90,8 @@ SubGhzProtocol* subghz_protocol_alloc() {
|
|||||||
(SubGhzProtocolCommon*)subghz_protocol_nero_sketch_alloc();
|
(SubGhzProtocolCommon*)subghz_protocol_nero_sketch_alloc();
|
||||||
instance->protocols[SubGhzProtocolTypeStarLine] =
|
instance->protocols[SubGhzProtocolTypeStarLine] =
|
||||||
(SubGhzProtocolCommon*)subghz_protocol_star_line_alloc(instance->keystore);
|
(SubGhzProtocolCommon*)subghz_protocol_star_line_alloc(instance->keystore);
|
||||||
|
instance->protocols[SubGhzProtocolTypeNeroRadio] =
|
||||||
|
(SubGhzProtocolCommon*)subghz_protocol_nero_radio_alloc();
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@ -113,6 +117,8 @@ void subghz_protocol_free(SubGhzProtocol* instance) {
|
|||||||
(SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]);
|
(SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]);
|
||||||
subghz_protocol_star_line_free(
|
subghz_protocol_star_line_free(
|
||||||
(SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]);
|
(SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]);
|
||||||
|
subghz_protocol_nero_radio_free(
|
||||||
|
(SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio]);
|
||||||
|
|
||||||
subghz_keystore_free(instance->keystore);
|
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) {
|
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(
|
subghz_protocol_nice_flor_s_name_file(
|
||||||
(SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name);
|
(SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name);
|
||||||
}
|
}
|
||||||
@ -191,6 +196,8 @@ void subghz_protocol_reset(SubGhzProtocol* instance) {
|
|||||||
(SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]);
|
(SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]);
|
||||||
subghz_protocol_star_line_reset(
|
subghz_protocol_star_line_reset(
|
||||||
(SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]);
|
(SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]);
|
||||||
|
subghz_protocol_nero_radio_reset(
|
||||||
|
(SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration) {
|
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);
|
duration);
|
||||||
subghz_protocol_star_line_parse(
|
subghz_protocol_star_line_parse(
|
||||||
(SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine], level, duration);
|
(SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine], level, duration);
|
||||||
|
subghz_protocol_nero_radio_parse(
|
||||||
|
(SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio],
|
||||||
|
level,
|
||||||
|
duration);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance);
|
|||||||
|
|
||||||
/** Get upload protocol
|
/** Get upload protocol
|
||||||
*
|
*
|
||||||
* @param instance - SubGhzProtocolCame instance
|
* @param instance - SubGhzProtocolGateTX instance
|
||||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -398,7 +398,7 @@ void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t outp
|
|||||||
string_cat_printf(
|
string_cat_printf(
|
||||||
output,
|
output,
|
||||||
"%s %dbit\r\n"
|
"%s %dbit\r\n"
|
||||||
"Key:0x%lX%lX\r\n"
|
"Key:%08lX%08lX\r\n"
|
||||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||||
"MF:%s\r\n"
|
"MF:%s\r\n"
|
||||||
|
@ -49,7 +49,7 @@ uint64_t subghz_protocol_keeloq_gen_key(void* context);
|
|||||||
|
|
||||||
/** Get upload protocol
|
/** Get upload protocol
|
||||||
*
|
*
|
||||||
* @param instance - SubGhzProtocolCame instance
|
* @param instance - SubGhzProtocolKeeloq instance
|
||||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
280
lib/subghz/protocols/subghz_protocol_nero_radio.c
Normal file
280
lib/subghz/protocols/subghz_protocol_nero_radio.c
Normal file
@ -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;
|
||||||
|
}
|
72
lib/subghz/protocols/subghz_protocol_nero_radio.h
Normal file
72
lib/subghz/protocols/subghz_protocol_nero_radio.h
Normal file
@ -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);
|
@ -18,7 +18,7 @@ void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance);
|
|||||||
|
|
||||||
/** Get upload protocol
|
/** Get upload protocol
|
||||||
*
|
*
|
||||||
* @param instance - SubGhzProtocolCame instance
|
* @param instance - SubGhzProtocolNeroSketch instance
|
||||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -18,7 +18,7 @@ void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance);
|
|||||||
|
|
||||||
/** Get upload protocol
|
/** Get upload protocol
|
||||||
*
|
*
|
||||||
* @param instance - SubGhzProtocolCame instance
|
* @param instance - SubGhzProtocolNiceFlo instance
|
||||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -172,7 +172,7 @@ void subghz_decoder_princeton_parse(
|
|||||||
if(!level) {
|
if(!level) {
|
||||||
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
||||||
instance->common.parser_step = 1;
|
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) {
|
instance->common.code_min_count_bit_for_found) {
|
||||||
if(instance->common.code_last_found == instance->common.code_found) {
|
if(instance->common.code_last_found == instance->common.code_found) {
|
||||||
//instance->te = (instance->te+instance->common.te_last)/2; //Option 1 TE averaging
|
//instance->te = (instance->te+instance->common.te_last)/2; //Option 1 TE averaging
|
||||||
|
@ -282,7 +282,7 @@ void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t
|
|||||||
string_cat_printf(
|
string_cat_printf(
|
||||||
output,
|
output,
|
||||||
"%s %dbit\r\n"
|
"%s %dbit\r\n"
|
||||||
"Key:0x%lX%lX\r\n"
|
"Key:%08lX%08lX\r\n"
|
||||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||||
"MF:%s\r\n"
|
"MF:%s\r\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user