[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, 84, item_text_y, string_get_cstr(item->current_value_text));
|
||||
canvas_draw_str(canvas, 80, item_text_y, string_get_cstr(item->current_value_text));
|
||||
|
||||
if(item->current_value_index < (item->values_count - 1)) {
|
||||
canvas_draw_str(canvas, 113, item_text_y, ">");
|
||||
canvas_draw_str(canvas, 115, item_text_y, ">");
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,6 +235,21 @@ void variable_item_list_free(VariableItemList* variable_item_list) {
|
||||
free(variable_item_list);
|
||||
}
|
||||
|
||||
void variable_item_list_clean(VariableItemList* variable_item_list) {
|
||||
furi_assert(variable_item_list);
|
||||
|
||||
with_view_model(
|
||||
variable_item_list->view, (VariableItemListModel * model) {
|
||||
VariableItemArray_it_t it;
|
||||
for(VariableItemArray_it(it, model->items); !VariableItemArray_end_p(it);
|
||||
VariableItemArray_next(it)) {
|
||||
string_clean(VariableItemArray_ref(it)->current_value_text);
|
||||
}
|
||||
VariableItemArray_clean(model->items);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
View* variable_item_list_get_view(VariableItemList* variable_item_list) {
|
||||
furi_assert(variable_item_list);
|
||||
return variable_item_list->view;
|
||||
|
@ -18,6 +18,9 @@ VariableItemList* variable_item_list_alloc();
|
||||
* @param variable_item_list VariableItemList instance
|
||||
*/
|
||||
void variable_item_list_free(VariableItemList* variable_item_list);
|
||||
|
||||
void variable_item_list_clean(VariableItemList* variable_item_list);
|
||||
|
||||
View* variable_item_list_get_view(VariableItemList* variable_item_list);
|
||||
|
||||
/** Add item to VariableItemList
|
||||
|
@ -118,6 +118,20 @@ static void widget_add_element(Widget* widget, WidgetElement* element) {
|
||||
});
|
||||
}
|
||||
|
||||
void widget_add_string_multi_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
Align horizontal,
|
||||
Align vertical,
|
||||
Font font,
|
||||
const char* text) {
|
||||
furi_assert(widget);
|
||||
WidgetElement* string_multi_element =
|
||||
widget_element_string_multi_create(x, y, horizontal, vertical, font, text);
|
||||
widget_add_element(widget, string_multi_element);
|
||||
}
|
||||
|
||||
void widget_add_string_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
|
@ -26,6 +26,23 @@ void widget_clear(Widget* widget);
|
||||
*/
|
||||
View* widget_get_view(Widget* widget);
|
||||
|
||||
/** Add Multi String Element
|
||||
* @param widget Widget instance
|
||||
* @param x - x coordinate
|
||||
* @param y - y coordinate
|
||||
* @param horizontal - Align instance
|
||||
* @param vertical - Align instance
|
||||
* @param font Font instance
|
||||
*/
|
||||
void widget_add_string_multi_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
Align horizontal,
|
||||
Align vertical,
|
||||
Font font,
|
||||
const char* text);
|
||||
|
||||
/** Add String Element
|
||||
* @param widget Widget instance
|
||||
* @param x - x coordinate
|
||||
|
@ -30,7 +30,18 @@ static bool gui_button_input(InputEvent* event, WidgetElement* element) {
|
||||
GuiButtonModel* model = element->model;
|
||||
bool consumed = false;
|
||||
|
||||
if((event->type == InputTypeShort) && model->callback) {
|
||||
if(model->callback == NULL) return consumed;
|
||||
|
||||
if(event->key == InputKeyOk && event->type == InputTypePress &&
|
||||
model->button_type == GuiButtonTypeCenter) {
|
||||
model->callback(GuiButtonTypeCenterPress, model->context);
|
||||
consumed = true;
|
||||
} else if(
|
||||
event->key == InputKeyOk && event->type == InputTypeRelease &&
|
||||
model->button_type == GuiButtonTypeCenter) {
|
||||
model->callback(GuiButtonTypeCenterRelease, model->context);
|
||||
consumed = true;
|
||||
} else if(event->type == InputTypeShort) {
|
||||
if((model->button_type == GuiButtonTypeLeft) && (event->key == InputKeyLeft)) {
|
||||
model->callback(model->button_type, model->context);
|
||||
consumed = true;
|
||||
|
@ -6,6 +6,8 @@ typedef enum {
|
||||
GuiButtonTypeLeft,
|
||||
GuiButtonTypeCenter,
|
||||
GuiButtonTypeRight,
|
||||
GuiButtonTypeCenterPress,
|
||||
GuiButtonTypeCenterRelease,
|
||||
} GuiButtonType;
|
||||
|
||||
typedef void (*ButtonCallback)(GuiButtonType result, void* context);
|
||||
@ -28,6 +30,15 @@ struct WidgetElement {
|
||||
Widget* parent;
|
||||
};
|
||||
|
||||
/* Create multi string element */
|
||||
WidgetElement* widget_element_string_multi_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
Align horizontal,
|
||||
Align vertical,
|
||||
Font font,
|
||||
const char* text);
|
||||
|
||||
/* Create string element */
|
||||
WidgetElement* widget_element_string_create(
|
||||
uint8_t x,
|
||||
|
@ -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, receiver, Receiver)
|
||||
ADD_SCENE(subghz, receiver_config, ReceiverConfig)
|
||||
ADD_SCENE(subghz, receiver_info, ReceiverInfo)
|
||||
ADD_SCENE(subghz, save_name, SaveName)
|
||||
ADD_SCENE(subghz, save_success, SaveSuccess)
|
||||
ADD_SCENE(subghz, saved, Saved)
|
||||
ADD_SCENE(subghz, transmitter, Transmitter)
|
||||
ADD_SCENE(subghz, no_man, NoMan)
|
||||
ADD_SCENE(subghz, show_error, ShowError)
|
||||
ADD_SCENE(subghz, test, Test)
|
||||
ADD_SCENE(subghz, test_static, TestStatic)
|
||||
ADD_SCENE(subghz, test_carrier, TestCarrier)
|
||||
|
@ -1,21 +1,102 @@
|
||||
#include "../subghz_i.h"
|
||||
#include "../views/subghz_receiver.h"
|
||||
|
||||
static void subghz_scene_receiver_update_statusbar(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
char frequency_str[20];
|
||||
char preset_str[10];
|
||||
string_t history_stat_str;
|
||||
string_init(history_stat_str);
|
||||
if(!subghz_history_get_text_space_left(subghz->txrx->history, history_stat_str)) {
|
||||
snprintf(
|
||||
frequency_str,
|
||||
sizeof(frequency_str),
|
||||
"%03ld.%02ld",
|
||||
subghz->txrx->frequency / 1000000 % 1000,
|
||||
subghz->txrx->frequency / 10000 % 100);
|
||||
if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
|
||||
snprintf(preset_str, sizeof(preset_str), "AM");
|
||||
} else if(subghz->txrx->preset == FuriHalSubGhzPreset2FSKAsync) {
|
||||
snprintf(preset_str, sizeof(preset_str), "FM");
|
||||
} else {
|
||||
furi_check(0);
|
||||
}
|
||||
subghz_receiver_add_data_statusbar(
|
||||
subghz->subghz_receiver, frequency_str, preset_str, string_get_cstr(history_stat_str));
|
||||
} else {
|
||||
subghz_receiver_add_data_statusbar(
|
||||
subghz->subghz_receiver, string_get_cstr(history_stat_str), "", "");
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
}
|
||||
string_clear(history_stat_str);
|
||||
}
|
||||
|
||||
void subghz_scene_receiver_callback(SubghzReceverEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void subghz_scene_add_to_history_callback(SubGhzProtocolCommon* parser, void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
string_t str_buff;
|
||||
string_init(str_buff);
|
||||
|
||||
if(subghz_history_add_to_history(
|
||||
subghz->txrx->history, parser, subghz->txrx->frequency, subghz->txrx->preset)) {
|
||||
subghz_protocol_reset(subghz->txrx->protocol);
|
||||
string_clean(str_buff);
|
||||
subghz_history_get_text_item_menu(
|
||||
subghz->txrx->history, str_buff, subghz_history_get_item(subghz->txrx->history) - 1);
|
||||
subghz_receiver_add_item_to_menu(
|
||||
subghz->subghz_receiver,
|
||||
string_get_cstr(str_buff),
|
||||
subghz_history_get_type_protocol(
|
||||
subghz->txrx->history, subghz_history_get_item(subghz->txrx->history) - 1));
|
||||
subghz_scene_receiver_update_statusbar(subghz);
|
||||
}
|
||||
string_clear(str_buff);
|
||||
}
|
||||
|
||||
const void subghz_scene_receiver_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
SubghzReceiver* subghz_receiver = subghz->subghz_receiver;
|
||||
|
||||
subghz_receiver_set_callback(subghz_receiver, subghz_scene_receiver_callback, subghz);
|
||||
string_t str_buff;
|
||||
string_init(str_buff);
|
||||
|
||||
//Load history to receiver
|
||||
subghz_receiver_exit(subghz->subghz_receiver);
|
||||
for(uint8_t i = 0; i < subghz_history_get_item(subghz->txrx->history); i++) {
|
||||
string_clean(str_buff);
|
||||
subghz_history_get_text_item_menu(subghz->txrx->history, str_buff, i);
|
||||
subghz_receiver_add_item_to_menu(
|
||||
subghz->subghz_receiver,
|
||||
string_get_cstr(str_buff),
|
||||
subghz_history_get_type_protocol(subghz->txrx->history, i));
|
||||
}
|
||||
string_clear(str_buff);
|
||||
subghz_scene_receiver_update_statusbar(subghz);
|
||||
subghz_receiver_set_callback(subghz->subghz_receiver, subghz_scene_receiver_callback, subghz);
|
||||
subghz_protocol_enable_dump(
|
||||
subghz->txrx->protocol, subghz_scene_add_to_history_callback, subghz);
|
||||
|
||||
subghz_receiver_set_protocol(subghz_receiver, subghz->protocol_result, subghz->protocol);
|
||||
subghz_receiver_set_worker(subghz_receiver, subghz->worker);
|
||||
subghz->state_notifications = NOTIFICATION_RX_STATE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
//subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
};
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
subghz_begin(subghz->txrx->preset);
|
||||
subghz_rx(subghz->txrx->worker, subghz->txrx->frequency);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateRx;
|
||||
}
|
||||
if(subghz->txrx->idx_menu_chosen != 0) {
|
||||
subghz_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewReceiver);
|
||||
}
|
||||
|
||||
@ -24,51 +105,43 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case SubghzReceverEventSave:
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->frequency = subghz_receiver_get_frequency(subghz->subghz_receiver);
|
||||
subghz->preset = subghz_receiver_get_preset(subghz->subghz_receiver);
|
||||
subghz->protocol_result = subghz_receiver_get_protocol(subghz->subghz_receiver);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
|
||||
return true;
|
||||
break;
|
||||
case SubghzReceverEventBack:
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
// Stop CC1101 Rx
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
};
|
||||
subghz_history_clean(subghz->txrx->history);
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
||||
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
|
||||
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
|
||||
subghz->txrx->idx_menu_chosen = 0;
|
||||
subghz_protocol_enable_dump(subghz->txrx->protocol, NULL, subghz);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
return true;
|
||||
break;
|
||||
case SubghzReceverEventSendStart:
|
||||
subghz->state_notifications = NOTIFICATION_TX_STATE;
|
||||
subghz->frequency = subghz_receiver_get_frequency(subghz->subghz_receiver);
|
||||
subghz->preset = subghz_receiver_get_preset(subghz->subghz_receiver);
|
||||
subghz->protocol_result = subghz_receiver_get_protocol(subghz->subghz_receiver);
|
||||
subghz_transmitter_tx_start(subghz);
|
||||
return true;
|
||||
break;
|
||||
case SubghzReceverEventSendStop:
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz_transmitter_tx_stop(subghz);
|
||||
return true;
|
||||
break;
|
||||
case SubghzReceverEventMain:
|
||||
subghz->state_notifications = NOTIFICATION_RX_STATE;
|
||||
case SubghzReceverEventOK:
|
||||
subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo);
|
||||
return true;
|
||||
break;
|
||||
case SubghzReceverEventConfig:
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
return true;
|
||||
break;
|
||||
case SubghzReceverEventSendHistoryFull:
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) {
|
||||
subghz_hopper_update(subghz->txrx);
|
||||
subghz_scene_receiver_update_statusbar(subghz);
|
||||
}
|
||||
|
||||
switch(subghz->state_notifications) {
|
||||
case NOTIFICATION_TX_STATE:
|
||||
notification_message(subghz->notifications, &sequence_blink_red_10);
|
||||
break;
|
||||
case NOTIFICATION_RX_STATE:
|
||||
notification_message(subghz->notifications, &sequence_blink_blue_10);
|
||||
break;
|
||||
|
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.event == SCENE_SAVE_NAME_CUSTOM_EVENT) {
|
||||
if(subghz_save_protocol_to_file(subghz, subghz->text_store)) {
|
||||
if(strcmp(subghz->text_store, "") &&
|
||||
subghz_save_protocol_to_file(subghz, subghz->text_store)) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess);
|
||||
return true;
|
||||
} else {
|
||||
//Error save
|
||||
string_set(subghz->error_str, "No name file");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -8,15 +8,18 @@ enum SubmenuIndex {
|
||||
SubmenuIndexCAME12bit,
|
||||
SubmenuIndexCAME24bit,
|
||||
SubmenuIndexNeroSketch,
|
||||
SubmenuIndexNeroRadio,
|
||||
SubmenuIndexGateTX,
|
||||
SubmenuIndexDoorHan,
|
||||
};
|
||||
|
||||
bool subghz_scene_set_type_submenu_to_find_protocol(void* context, const char* protocol_name) {
|
||||
SubGhz* subghz = context;
|
||||
subghz->protocol_result = subghz_protocol_get_by_name(subghz->protocol, protocol_name);
|
||||
if(subghz->protocol_result == NULL) {
|
||||
//show error
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->txrx->protocol, protocol_name);
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
string_set(subghz->error_str, "Protocol not found");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -62,6 +65,8 @@ const void subghz_scene_set_type_on_enter(void* context) {
|
||||
subghz);
|
||||
// submenu_add_item(
|
||||
// subghz->submenu, "Nero Sketch", SubmenuIndexNeroSketch, subghz_scene_set_type_submenu_callback, subghz);
|
||||
// submenu_add_item(
|
||||
// subghz->submenu, "Nero Radio", SubmenuIndexNeroRadio, subghz_scene_set_type_submenu_callback, subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"Gate TX_433",
|
||||
@ -90,81 +95,86 @@ const bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event
|
||||
switch(event.event) {
|
||||
case SubmenuIndexPricenton:
|
||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "Princeton")) {
|
||||
subghz->protocol_result->code_last_count_bit = 24;
|
||||
subghz->txrx->protocol_result->code_last_count_bit = 24;
|
||||
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
|
||||
subghz->protocol_result->code_last_found = key;
|
||||
subghz->txrx->protocol_result->code_last_found = key;
|
||||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexNiceFlo12bit:
|
||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "Nice FLO")) {
|
||||
subghz->protocol_result->code_last_count_bit = 12;
|
||||
subghz->txrx->protocol_result->code_last_count_bit = 12;
|
||||
key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
|
||||
subghz->protocol_result->code_last_found = key;
|
||||
subghz->txrx->protocol_result->code_last_found = key;
|
||||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexNiceFlo24bit:
|
||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "Nice FLO")) {
|
||||
subghz->protocol_result->code_last_count_bit = 24;
|
||||
subghz->txrx->protocol_result->code_last_count_bit = 24;
|
||||
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
|
||||
subghz->protocol_result->code_last_found = key;
|
||||
subghz->txrx->protocol_result->code_last_found = key;
|
||||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexCAME12bit:
|
||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "CAME")) {
|
||||
subghz->protocol_result->code_last_count_bit = 12;
|
||||
subghz->txrx->protocol_result->code_last_count_bit = 12;
|
||||
key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4
|
||||
subghz->protocol_result->code_last_found = key;
|
||||
subghz->txrx->protocol_result->code_last_found = key;
|
||||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexCAME24bit:
|
||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "CAME")) {
|
||||
subghz->protocol_result->code_last_count_bit = 24;
|
||||
subghz->txrx->protocol_result->code_last_count_bit = 24;
|
||||
key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8
|
||||
subghz->protocol_result->code_last_found = key;
|
||||
subghz->txrx->protocol_result->code_last_found = key;
|
||||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
// case SubmenuIndexNeroSketch:
|
||||
// /* code */
|
||||
// break;
|
||||
// case SubmenuIndexNeroRadio:
|
||||
// /* code */
|
||||
// break;
|
||||
case SubmenuIndexGateTX:
|
||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "GateTX")) {
|
||||
subghz->protocol_result->code_last_count_bit = 24;
|
||||
subghz->txrx->protocol_result->code_last_count_bit = 24;
|
||||
key = (key & 0x00F0FFFF) | 0xF << 16; //btn 0xF, 0xC, 0xA, 0x6
|
||||
subghz->protocol_result->code_last_found = subghz_protocol_common_reverse_key(
|
||||
key, subghz->protocol_result->code_last_count_bit);
|
||||
subghz->txrx->protocol_result->code_last_found =
|
||||
subghz_protocol_common_reverse_key(
|
||||
key, subghz->txrx->protocol_result->code_last_count_bit);
|
||||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexDoorHan:
|
||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "KeeLoq")) {
|
||||
subghz->protocol_result->code_last_count_bit = 64;
|
||||
subghz->protocol_result->serial = key & 0x0FFFFFFF;
|
||||
subghz->protocol_result->btn = 0x2; //btn 0x1, 0x2, 0x4, 0x8
|
||||
subghz->protocol_result->cnt = 0x0003;
|
||||
subghz->txrx->protocol_result->code_last_count_bit = 64;
|
||||
subghz->txrx->protocol_result->serial = key & 0x0FFFFFFF;
|
||||
subghz->txrx->protocol_result->btn = 0x2; //btn 0x1, 0x2, 0x4, 0x8
|
||||
subghz->txrx->protocol_result->cnt = 0x0003;
|
||||
if(subghz_protocol_keeloq_set_manufacture_name(
|
||||
subghz->protocol_result, "DoorHan")) {
|
||||
subghz->protocol_result->code_last_found =
|
||||
subghz_protocol_keeloq_gen_key(subghz->protocol_result);
|
||||
subghz->txrx->protocol_result, "DoorHan")) {
|
||||
subghz->txrx->protocol_result->code_last_found =
|
||||
subghz_protocol_keeloq_gen_key(subghz->txrx->protocol_result);
|
||||
generated_protocol = true;
|
||||
} else {
|
||||
generated_protocol = false;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNoMan);
|
||||
string_set(subghz->error_str, "No manufactory key");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(generated_protocol) {
|
||||
subghz->frequency = subghz_frequencies[subghz_frequencies_433_92];
|
||||
subghz->preset = FuriHalSubGhzPresetOok650Async;
|
||||
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
|
||||
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
|
||||
return true;
|
||||
}
|
||||
|
@ -2,26 +2,26 @@
|
||||
|
||||
#define SCENE_NO_MAN_CUSTOM_EVENT (11UL)
|
||||
|
||||
void subghz_scene_no_man_popup_callback(void* context) {
|
||||
void subghz_scene_show_error_popup_callback(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_NO_MAN_CUSTOM_EVENT);
|
||||
}
|
||||
|
||||
const void subghz_scene_no_man_on_enter(void* context) {
|
||||
const void subghz_scene_show_error_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
// Setup view
|
||||
Popup* popup = subghz->popup;
|
||||
popup_set_icon(popup, 32, 12, &I_DolphinFirstStart7_61x51);
|
||||
popup_set_header(popup, "No manufactory key", 13, 8, AlignLeft, AlignBottom);
|
||||
popup_set_header(popup, string_get_cstr(subghz->error_str), 64, 8, AlignCenter, AlignBottom);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_set_context(popup, subghz);
|
||||
popup_set_callback(popup, subghz_scene_no_man_popup_callback);
|
||||
popup_set_callback(popup, subghz_scene_show_error_popup_callback);
|
||||
popup_enable_timeout(popup);
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewPopup);
|
||||
}
|
||||
|
||||
const bool subghz_scene_no_man_on_event(void* context, SceneManagerEvent event) {
|
||||
const bool subghz_scene_show_error_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SCENE_NO_MAN_CUSTOM_EVENT) {
|
||||
@ -33,7 +33,7 @@ const bool subghz_scene_no_man_on_event(void* context, SceneManagerEvent event)
|
||||
return false;
|
||||
}
|
||||
|
||||
const void subghz_scene_no_man_on_exit(void* context) {
|
||||
const void subghz_scene_show_error_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
// Clear view
|
||||
@ -45,4 +45,5 @@ const void subghz_scene_no_man_on_exit(void* context) {
|
||||
popup_set_context(popup, NULL);
|
||||
popup_set_timeout(popup, 0);
|
||||
popup_disable_timeout(popup);
|
||||
string_clean(subghz->error_str);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "../subghz_i.h"
|
||||
#include "../views/subghz_transmitter.h"
|
||||
#include <lib/subghz/protocols/subghz_protocol_keeloq.h>
|
||||
|
||||
void subghz_scene_transmitter_callback(SubghzTransmitterEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
@ -7,42 +8,90 @@ void subghz_scene_transmitter_callback(SubghzTransmitterEvent event, void* conte
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, event);
|
||||
}
|
||||
|
||||
static void subghz_scene_transmitter_update_data_show(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->get_upload_protocol) {
|
||||
string_t key_str;
|
||||
string_init(key_str);
|
||||
char frequency_str[10];
|
||||
char preset_str[6];
|
||||
uint8_t show_button = 0;
|
||||
subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, key_str);
|
||||
|
||||
if((!strcmp(subghz->txrx->protocol_result->name, "KeeLoq")) &&
|
||||
(!strcmp(
|
||||
subghz_protocol_keeloq_get_manufacture_name(subghz->txrx->protocol_result),
|
||||
"Unknown"))) {
|
||||
show_button = 0;
|
||||
} else {
|
||||
show_button = 1;
|
||||
}
|
||||
snprintf(
|
||||
frequency_str,
|
||||
sizeof(frequency_str),
|
||||
"%03ld.%02ld",
|
||||
subghz->txrx->frequency / 1000000 % 1000,
|
||||
subghz->txrx->frequency / 10000 % 100);
|
||||
if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async ||
|
||||
subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) {
|
||||
snprintf(preset_str, sizeof(preset_str), "AM");
|
||||
} else if(subghz->txrx->preset == FuriHalSubGhzPreset2FSKAsync) {
|
||||
snprintf(preset_str, sizeof(preset_str), "FM");
|
||||
} else {
|
||||
furi_check(0);
|
||||
}
|
||||
|
||||
subghz_transmitter_add_data_to_show(
|
||||
subghz->subghz_transmitter,
|
||||
string_get_cstr(key_str),
|
||||
frequency_str,
|
||||
preset_str,
|
||||
show_button);
|
||||
string_clear(key_str);
|
||||
} else {
|
||||
string_set(subghz->error_str, "Protocol not found");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
}
|
||||
}
|
||||
|
||||
const void subghz_scene_transmitter_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
SubghzTransmitter* subghz_transmitter = subghz->subghz_transmitter;
|
||||
|
||||
subghz_transmitter_set_callback(subghz_transmitter, subghz_scene_transmitter_callback, subghz);
|
||||
subghz_transmitter_set_protocol(subghz_transmitter, subghz->protocol_result);
|
||||
subghz_transmitter_set_frequency_preset(subghz_transmitter, subghz->frequency, subghz->preset);
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTransmitter);
|
||||
|
||||
subghz_transmitter_set_callback(
|
||||
subghz->subghz_transmitter, subghz_scene_transmitter_callback, subghz);
|
||||
subghz_scene_transmitter_update_data_show(subghz);
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTransmitter);
|
||||
}
|
||||
|
||||
const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubghzTransmitterEventSendStart) {
|
||||
subghz->state_notifications = NOTIFICATION_TX_STATE;
|
||||
subghz_transmitter_tx_start(subghz);
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
}
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
subghz_tx_start(subghz);
|
||||
subghz_scene_transmitter_update_data_show(subghz);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateTx;
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubghzTransmitterEventSendStop) {
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz_transmitter_tx_stop(subghz);
|
||||
subghz_sleep();
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubghzTransmitterEventBack) {
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
return true;
|
||||
} else if(event.event == SubghzTransmitterEventNoMan) {
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneNoMan);
|
||||
return true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subghz->state_notifications == NOTIFICATION_TX_STATE) {
|
||||
@ -55,7 +104,6 @@ const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent ev
|
||||
|
||||
const void subghz_scene_transmitter_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
SubghzTransmitter* subghz_transmitter = subghz->subghz_transmitter;
|
||||
subghz_transmitter_set_callback(subghz_transmitter, NULL, subghz);
|
||||
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
}
|
||||
|
@ -1,5 +1,22 @@
|
||||
#include "subghz_i.h"
|
||||
|
||||
const char* const subghz_frequencies_text[] = {
|
||||
"300.00",
|
||||
"315.00",
|
||||
"348.00",
|
||||
"387.00",
|
||||
"433.08",
|
||||
"433.92",
|
||||
"434.78",
|
||||
"438.90",
|
||||
"464.00",
|
||||
"779.00",
|
||||
"868.35",
|
||||
"915.00",
|
||||
"925.00",
|
||||
"928.00",
|
||||
};
|
||||
|
||||
const uint32_t subghz_frequencies[] = {
|
||||
/* 300 - 348 */
|
||||
300000000,
|
||||
@ -20,7 +37,15 @@ const uint32_t subghz_frequencies[] = {
|
||||
928000000,
|
||||
};
|
||||
|
||||
const uint32_t subghz_hopper_frequencies[] = {
|
||||
315000000,
|
||||
433920000,
|
||||
868350000,
|
||||
};
|
||||
|
||||
const uint32_t subghz_frequencies_count = sizeof(subghz_frequencies) / sizeof(uint32_t);
|
||||
const uint32_t subghz_hopper_frequencies_count =
|
||||
sizeof(subghz_hopper_frequencies) / sizeof(uint32_t);
|
||||
const uint32_t subghz_frequencies_433_92 = 5;
|
||||
|
||||
bool subghz_custom_event_callback(void* context, uint32_t event) {
|
||||
@ -77,11 +102,6 @@ SubGhz* subghz_alloc() {
|
||||
SubGhzViewReceiver,
|
||||
subghz_receiver_get_view(subghz->subghz_receiver));
|
||||
|
||||
// Dialog
|
||||
subghz->dialog_ex = dialog_ex_alloc();
|
||||
view_dispatcher_add_view(
|
||||
subghz->view_dispatcher, SubGhzViewDialogEx, dialog_ex_get_view(subghz->dialog_ex));
|
||||
|
||||
// Popup
|
||||
subghz->popup = popup_alloc();
|
||||
view_dispatcher_add_view(
|
||||
@ -92,6 +112,11 @@ SubGhz* subghz_alloc() {
|
||||
view_dispatcher_add_view(
|
||||
subghz->view_dispatcher, SubGhzViewTextInput, text_input_get_view(subghz->text_input));
|
||||
|
||||
// Custom Widget
|
||||
subghz->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
subghz->view_dispatcher, SubGhzViewWidget, widget_get_view(subghz->widget));
|
||||
|
||||
// Transmitter
|
||||
subghz->subghz_transmitter = subghz_transmitter_alloc();
|
||||
view_dispatcher_add_view(
|
||||
@ -99,6 +124,13 @@ SubGhz* subghz_alloc() {
|
||||
SubGhzViewTransmitter,
|
||||
subghz_transmitter_get_view(subghz->subghz_transmitter));
|
||||
|
||||
// Variable Item List
|
||||
subghz->variable_item_list = variable_item_list_alloc();
|
||||
view_dispatcher_add_view(
|
||||
subghz->view_dispatcher,
|
||||
SubGhzViewVariableItemList,
|
||||
variable_item_list_get_view(subghz->variable_item_list));
|
||||
|
||||
// Carrier Test Module
|
||||
subghz->subghz_test_carrier = subghz_test_carrier_alloc();
|
||||
view_dispatcher_add_view(
|
||||
@ -120,17 +152,26 @@ SubGhz* subghz_alloc() {
|
||||
SubGhzViewStatic,
|
||||
subghz_test_static_get_view(subghz->subghz_test_static));
|
||||
|
||||
//init Worker & Protocol
|
||||
subghz->worker = subghz_worker_alloc();
|
||||
subghz->protocol = subghz_protocol_alloc();
|
||||
//init Worker & Protocol & History
|
||||
subghz->txrx = furi_alloc(sizeof(SubGhzTxRx));
|
||||
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
|
||||
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
||||
subghz->txrx->history = subghz_history_alloc();
|
||||
subghz->txrx->worker = subghz_worker_alloc();
|
||||
subghz->txrx->protocol = subghz_protocol_alloc();
|
||||
subghz_worker_set_overrun_callback(
|
||||
subghz->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset);
|
||||
subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset);
|
||||
subghz_worker_set_pair_callback(
|
||||
subghz->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse);
|
||||
subghz_worker_set_context(subghz->worker, subghz->protocol);
|
||||
subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse);
|
||||
subghz_worker_set_context(subghz->txrx->worker, subghz->txrx->protocol);
|
||||
|
||||
subghz_protocol_load_keeloq_file(subghz->protocol, "/ext/subghz/keeloq_mfcodes");
|
||||
subghz_protocol_load_nice_flor_s_file(subghz->protocol, "/ext/subghz/nice_floor_s_rx");
|
||||
//Init Error_str
|
||||
string_init(subghz->error_str);
|
||||
|
||||
subghz_protocol_load_keeloq_file(subghz->txrx->protocol, "/ext/subghz/keeloq_mfcodes");
|
||||
subghz_protocol_load_nice_flor_s_file(subghz->txrx->protocol, "/ext/subghz/nice_floor_s_rx");
|
||||
|
||||
//subghz_protocol_enable_dump_text(subghz->protocol, subghz_text_callback, subghz);
|
||||
|
||||
@ -160,18 +201,22 @@ void subghz_free(SubGhz* subghz) {
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTextInput);
|
||||
text_input_free(subghz->text_input);
|
||||
|
||||
// Receiver
|
||||
// Custom Widget
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewWidget);
|
||||
widget_free(subghz->widget);
|
||||
|
||||
// Transmitter
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTransmitter);
|
||||
subghz_transmitter_free(subghz->subghz_transmitter);
|
||||
|
||||
// Variable Item List
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewVariableItemList);
|
||||
variable_item_list_free(subghz->variable_item_list);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewMenu);
|
||||
submenu_free(subghz->submenu);
|
||||
|
||||
// DialogEx
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewDialogEx);
|
||||
dialog_ex_free(subghz->dialog_ex);
|
||||
|
||||
// Popup
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewPopup);
|
||||
popup_free(subghz->popup);
|
||||
@ -186,9 +231,14 @@ void subghz_free(SubGhz* subghz) {
|
||||
furi_record_close("gui");
|
||||
subghz->gui = NULL;
|
||||
|
||||
//Worker & Protocol
|
||||
subghz_protocol_free(subghz->protocol);
|
||||
subghz_worker_free(subghz->worker);
|
||||
//Worker & Protocol & History
|
||||
subghz_protocol_free(subghz->txrx->protocol);
|
||||
subghz_worker_free(subghz->txrx->worker);
|
||||
subghz_history_free(subghz->txrx->history);
|
||||
free(subghz->txrx);
|
||||
|
||||
//Error string
|
||||
string_clear(subghz->error_str);
|
||||
|
||||
// Notifications
|
||||
furi_record_close("notification");
|
||||
|
@ -128,21 +128,27 @@ void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output,
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_history_add_to_history(SubGhzHistory* instance, void* context) {
|
||||
bool subghz_history_add_to_history(
|
||||
SubGhzHistory* instance,
|
||||
void* context,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset) {
|
||||
furi_assert(instance);
|
||||
furi_assert(context);
|
||||
SubGhzProtocolCommon* protocol = context;
|
||||
|
||||
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return;
|
||||
if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return false;
|
||||
if((instance->code_last_found == (protocol->code_last_found & 0xFFFF0FFFFFFFFFFF)) &&
|
||||
((millis() - instance->last_update_timestamp) < 500)) {
|
||||
instance->last_update_timestamp = millis();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
instance->code_last_found = protocol->code_last_found & 0xFFFF0FFFFFFFFFFF;
|
||||
instance->last_update_timestamp = millis();
|
||||
|
||||
instance->history[instance->last_index_write].real_frequency = frequency;
|
||||
instance->history[instance->last_index_write].preset = preset;
|
||||
instance->history[instance->last_index_write].te = 0;
|
||||
instance->history[instance->last_index_write].manufacture_name = NULL;
|
||||
instance->history[instance->last_index_write].name = protocol->name;
|
||||
@ -161,4 +167,5 @@ void subghz_history_add_to_history(SubGhzHistory* instance, void* context) {
|
||||
instance->history[instance->last_index_write].type_protocol = protocol->type_protocol;
|
||||
|
||||
instance->last_index_write++;
|
||||
return true;
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#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 context - SubGhzProtocolCommon context
|
||||
* @param frequency - frequency Hz
|
||||
* @param preset - FuriHalSubGhzPreset preset
|
||||
* @return bool;
|
||||
*/
|
||||
void subghz_history_add_to_history(SubGhzHistory* instance, void* context);
|
||||
bool subghz_history_add_to_history(
|
||||
SubGhzHistory* instance,
|
||||
void* context,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset);
|
||||
|
||||
/** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data
|
||||
*
|
||||
@ -104,3 +112,5 @@ void subghz_history_add_to_history(SubGhzHistory* instance, void* context);
|
||||
* @return SubGhzProtocolCommonLoad*
|
||||
*/
|
||||
SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
|
||||
|
||||
void subghz_hopper_update(void* context);
|
||||
|
@ -19,6 +19,9 @@ void subghz_begin(FuriHalSubGhzPreset preset) {
|
||||
|
||||
uint32_t subghz_rx(void* context, uint32_t frequency) {
|
||||
furi_assert(context);
|
||||
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
|
||||
furi_check(0);
|
||||
}
|
||||
SubGhzWorker* worker = context;
|
||||
|
||||
furi_hal_subghz_idle();
|
||||
@ -33,6 +36,9 @@ uint32_t subghz_rx(void* context, uint32_t frequency) {
|
||||
}
|
||||
|
||||
uint32_t subghz_tx(uint32_t frequency) {
|
||||
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
|
||||
furi_check(0);
|
||||
}
|
||||
furi_hal_subghz_idle();
|
||||
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
@ -53,6 +59,7 @@ void subghz_rx_end(void* context) {
|
||||
subghz_worker_stop(worker);
|
||||
furi_hal_subghz_stop_async_rx();
|
||||
}
|
||||
furi_hal_subghz_idle();
|
||||
}
|
||||
|
||||
void subghz_sleep(void) {
|
||||
@ -66,41 +73,46 @@ void subghz_frequency_preset_to_str(void* context, string_t output) {
|
||||
output,
|
||||
"Frequency: %d\n"
|
||||
"Preset: %d\n",
|
||||
(int)subghz->frequency,
|
||||
(int)subghz->preset);
|
||||
(int)subghz->txrx->frequency,
|
||||
(int)subghz->txrx->preset);
|
||||
}
|
||||
|
||||
void subghz_transmitter_tx_start(void* context) {
|
||||
void subghz_tx_start(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
subghz->encoder = subghz_protocol_encoder_common_alloc();
|
||||
subghz->encoder->repeat = 200; //max repeat with the button held down
|
||||
subghz->txrx->encoder = subghz_protocol_encoder_common_alloc();
|
||||
subghz->txrx->encoder->repeat = 200; //max repeat with the button held down
|
||||
//get upload
|
||||
if(subghz->protocol_result->get_upload_protocol) {
|
||||
if(subghz->protocol_result->get_upload_protocol(subghz->protocol_result, subghz->encoder)) {
|
||||
if(subghz->preset) {
|
||||
subghz_begin(subghz->preset);
|
||||
if(subghz->txrx->protocol_result->get_upload_protocol) {
|
||||
if(subghz->txrx->protocol_result->get_upload_protocol(
|
||||
subghz->txrx->protocol_result, subghz->txrx->encoder)) {
|
||||
if(subghz->txrx->preset) {
|
||||
subghz_begin(subghz->txrx->preset);
|
||||
} else {
|
||||
subghz_begin(FuriHalSubGhzPresetOok650Async);
|
||||
subghz_begin(FuriHalSubGhzPresetOok270Async);
|
||||
}
|
||||
if(subghz->frequency) {
|
||||
subghz_tx(subghz->frequency);
|
||||
if(subghz->txrx->frequency) {
|
||||
subghz_tx(subghz->txrx->frequency);
|
||||
} else {
|
||||
subghz_tx(433920000);
|
||||
}
|
||||
|
||||
//Start TX
|
||||
furi_hal_subghz_start_async_tx(subghz_protocol_encoder_common_yield, subghz->encoder);
|
||||
furi_hal_subghz_start_async_tx(
|
||||
subghz_protocol_encoder_common_yield, subghz->txrx->encoder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_transmitter_tx_stop(void* context) {
|
||||
void subghz_tx_stop(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
//Stop TX
|
||||
furi_hal_subghz_stop_async_tx();
|
||||
subghz_protocol_encoder_common_free(subghz->encoder);
|
||||
subghz_protocol_encoder_common_free(subghz->txrx->encoder);
|
||||
furi_hal_subghz_idle();
|
||||
//if protocol dynamic then we save the last upload
|
||||
if(subghz->protocol_result->type_protocol == TYPE_PROTOCOL_DYNAMIC) {
|
||||
if(subghz->txrx->protocol_result->type_protocol == TYPE_PROTOCOL_DYNAMIC) {
|
||||
subghz_save_protocol_to_file(subghz, subghz->text_store);
|
||||
}
|
||||
notification_message(subghz->notifications, &sequence_reset_red);
|
||||
@ -133,7 +145,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
subghz->frequency = (uint32_t)data;
|
||||
subghz->txrx->frequency = (uint32_t)data;
|
||||
|
||||
// Read and parse preset from 2st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
@ -143,7 +155,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
if(res != 1) {
|
||||
break;
|
||||
}
|
||||
subghz->preset = (FuriHalSubGhzPreset)data;
|
||||
subghz->txrx->preset = (FuriHalSubGhzPreset)data;
|
||||
|
||||
// Read and parse name protocol from 2st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
@ -151,13 +163,13 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
}
|
||||
// strlen("Protocol: ") = 10
|
||||
string_right(temp_str, 10);
|
||||
subghz->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str));
|
||||
if(subghz->protocol_result == NULL) {
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str));
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
break;
|
||||
}
|
||||
if(!subghz->protocol_result->to_load_protocol_from_file(
|
||||
file_worker, subghz->protocol_result)) {
|
||||
if(!subghz->txrx->protocol_result->to_load_protocol_from_file(
|
||||
file_worker, subghz->txrx->protocol_result)) {
|
||||
break;
|
||||
}
|
||||
loaded = true;
|
||||
@ -175,8 +187,9 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
}
|
||||
|
||||
bool subghz_save_protocol_to_file(void* context, const char* dev_name) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
furi_assert(subghz->protocol_result);
|
||||
furi_assert(subghz->txrx->protocol_result);
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
string_t dev_file_name;
|
||||
string_init(dev_file_name);
|
||||
@ -210,7 +223,7 @@ bool subghz_save_protocol_to_file(void* context, const char* dev_name) {
|
||||
break;
|
||||
}
|
||||
//Get string save
|
||||
subghz->protocol_result->to_save_string(subghz->protocol_result, temp_str);
|
||||
subghz->txrx->protocol_result->to_save_string(subghz->txrx->protocol_result, temp_str);
|
||||
// Prepare and write data to file
|
||||
if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) {
|
||||
break;
|
||||
@ -276,7 +289,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) {
|
||||
if(sscanf_res != 1) {
|
||||
break;
|
||||
}
|
||||
subghz->frequency = (uint32_t)data;
|
||||
subghz->txrx->frequency = (uint32_t)data;
|
||||
|
||||
// Read and parse preset from 2st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
@ -286,7 +299,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) {
|
||||
if(sscanf_res != 1) {
|
||||
break;
|
||||
}
|
||||
subghz->preset = (FuriHalSubGhzPreset)data;
|
||||
subghz->txrx->preset = (FuriHalSubGhzPreset)data;
|
||||
|
||||
// Read and parse name protocol from 3st line
|
||||
if(!file_worker_read_until(file_worker, temp_str, '\n')) {
|
||||
@ -294,13 +307,13 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) {
|
||||
}
|
||||
// strlen("Protocol: ") = 10
|
||||
string_right(temp_str, 10);
|
||||
subghz->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str));
|
||||
if(subghz->protocol_result == NULL) {
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str));
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
break;
|
||||
}
|
||||
if(!subghz->protocol_result->to_load_protocol_from_file(
|
||||
file_worker, subghz->protocol_result)) {
|
||||
if(!subghz->txrx->protocol_result->to_load_protocol_from_file(
|
||||
file_worker, subghz->txrx->protocol_result)) {
|
||||
break;
|
||||
}
|
||||
res = true;
|
||||
@ -328,3 +341,57 @@ uint32_t subghz_random_serial(void) {
|
||||
}
|
||||
return (uint32_t)rand();
|
||||
}
|
||||
|
||||
void subghz_hopper_update(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTxRx* txrx = context;
|
||||
|
||||
switch(txrx->hopper_state) {
|
||||
case SubGhzHopperStateOFF:
|
||||
return;
|
||||
break;
|
||||
case SubGhzHopperStatePause:
|
||||
return;
|
||||
break;
|
||||
case SubGhzHopperStateRSSITimeOut:
|
||||
if(txrx->hopper_timeout != 0) {
|
||||
txrx->hopper_timeout--;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
float rssi = -127.0f;
|
||||
if(txrx->hopper_state != SubGhzHopperStateRSSITimeOut) {
|
||||
// See RSSI Calculation timings in CC1101 17.3 RSSI
|
||||
rssi = furi_hal_subghz_get_rssi();
|
||||
|
||||
// Stay if RSSI is high enough
|
||||
if(rssi > -90.0f) {
|
||||
txrx->hopper_timeout = 10;
|
||||
txrx->hopper_state = SubGhzHopperStateRSSITimeOut;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
txrx->hopper_state = SubGhzHopperStateRunnig;
|
||||
}
|
||||
|
||||
// Select next frequency
|
||||
if(txrx->hopper_idx_frequency < subghz_hopper_frequencies_count - 1) {
|
||||
txrx->hopper_idx_frequency++;
|
||||
} else {
|
||||
txrx->hopper_idx_frequency = 0;
|
||||
}
|
||||
|
||||
if(txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(txrx->worker);
|
||||
txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
};
|
||||
if(txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
subghz_protocol_reset(txrx->protocol);
|
||||
txrx->frequency = subghz_hopper_frequencies[txrx->hopper_idx_frequency];
|
||||
subghz_rx(txrx->worker, txrx->frequency);
|
||||
txrx->txrx_state = SubGhzTxRxStateRx;
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,9 @@
|
||||
#include <notification/notification-messages.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/dialog_ex.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
#include <subghz/scenes/subghz_scene.h>
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
||||
#include "subghz_history.h"
|
||||
|
||||
#include <gui/modules/variable-item-list.h>
|
||||
|
||||
#define SUBGHZ_TEXT_STORE_SIZE 128
|
||||
|
||||
#define NOTIFICATION_STARTING_STATE 0u
|
||||
@ -33,48 +35,81 @@
|
||||
#define NOTIFICATION_TX_STATE 2u
|
||||
#define NOTIFICATION_RX_STATE 3u
|
||||
|
||||
extern const char* const subghz_frequencies_text[];
|
||||
extern const uint32_t subghz_frequencies[];
|
||||
extern const uint32_t subghz_hopper_frequencies[];
|
||||
extern const uint32_t subghz_frequencies_count;
|
||||
extern const uint32_t subghz_hopper_frequencies_count;
|
||||
extern const uint32_t subghz_frequencies_433_92;
|
||||
|
||||
struct SubGhz {
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
/** SubGhzTxRx state */
|
||||
typedef enum {
|
||||
SubGhzTxRxStateIdle,
|
||||
SubGhzTxRxStateRx,
|
||||
SubGhzTxRxStateTx,
|
||||
} SubGhzTxRxState;
|
||||
|
||||
/** SubGhzHopperState state */
|
||||
typedef enum {
|
||||
SubGhzHopperStateOFF,
|
||||
SubGhzHopperStateRunnig,
|
||||
SubGhzHopperStatePause,
|
||||
SubGhzHopperStateRSSITimeOut,
|
||||
} SubGhzHopperState;
|
||||
|
||||
struct SubGhzTxRx {
|
||||
SubGhzWorker* worker;
|
||||
SubGhzProtocol* protocol;
|
||||
SubGhzProtocolCommon* protocol_result;
|
||||
SubGhzProtocolCommonEncoder* encoder;
|
||||
uint32_t frequency;
|
||||
FuriHalSubGhzPreset preset;
|
||||
SubGhzHistory* history;
|
||||
uint16_t idx_menu_chosen;
|
||||
SubGhzTxRxState txrx_state;
|
||||
//bool hopper_runing;
|
||||
SubGhzHopperState hopper_state;
|
||||
uint8_t hopper_timeout;
|
||||
uint8_t hopper_idx_frequency;
|
||||
};
|
||||
|
||||
typedef struct SubGhzTxRx SubGhzTxRx;
|
||||
|
||||
struct SubGhz {
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
|
||||
SubGhzTxRx* txrx;
|
||||
|
||||
SceneManager* scene_manager;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
|
||||
Submenu* submenu;
|
||||
DialogEx* dialog_ex;
|
||||
Popup* popup;
|
||||
TextInput* text_input;
|
||||
Widget* widget;
|
||||
char text_store[SUBGHZ_TEXT_STORE_SIZE + 1];
|
||||
uint8_t state_notifications;
|
||||
|
||||
SubghzReceiver* subghz_receiver;
|
||||
SubghzTransmitter* subghz_transmitter;
|
||||
VariableItemList* variable_item_list;
|
||||
|
||||
SubghzTestStatic* subghz_test_static;
|
||||
SubghzTestCarrier* subghz_test_carrier;
|
||||
SubghzTestPacket* subghz_test_packet;
|
||||
string_t error_str;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SubGhzViewMenu,
|
||||
|
||||
SubGhzViewDialogEx,
|
||||
SubGhzViewReceiver,
|
||||
SubGhzViewPopup,
|
||||
SubGhzViewTextInput,
|
||||
SubGhzViewWidget,
|
||||
SubGhzViewTransmitter,
|
||||
|
||||
SubGhzViewVariableItemList,
|
||||
SubGhzViewStatic,
|
||||
SubGhzViewTestCarrier,
|
||||
SubGhzViewTestPacket,
|
||||
@ -86,8 +121,8 @@ uint32_t subghz_tx(uint32_t frequency);
|
||||
void subghz_idle(void);
|
||||
void subghz_rx_end(void* context);
|
||||
void subghz_sleep(void);
|
||||
void subghz_transmitter_tx_start(void* context);
|
||||
void subghz_transmitter_tx_stop(void* context);
|
||||
void subghz_tx_start(void* context);
|
||||
void subghz_tx_stop(void* context);
|
||||
bool subghz_key_load(SubGhz* subghz, const char* file_path);
|
||||
bool subghz_save_protocol_to_file(void* context, const char* dev_name);
|
||||
bool subghz_load_protocol_from_file(SubGhz* subghz);
|
||||
|
@ -1,42 +1,32 @@
|
||||
#include "subghz_receiver.h"
|
||||
#include "../subghz_i.h"
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <notification/notification-messages.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_princeton.h>
|
||||
|
||||
#include <assets_icons.h>
|
||||
#include <m-string.h>
|
||||
#include <m-array.h>
|
||||
|
||||
#define FRAME_HEIGHT 12
|
||||
#define MAX_LEN_PX 100
|
||||
#define MENU_ITEMS 4
|
||||
|
||||
#define COUNT_FREQUNCY_HOPPER 3
|
||||
const uint32_t subghz_frequencies_hopper[] = {
|
||||
/* 300 - 348 */
|
||||
315000000,
|
||||
/* 387 - 464 */
|
||||
433920000, /* LPD433 mid */
|
||||
/* 779 - 928 */
|
||||
868350000,
|
||||
typedef struct {
|
||||
string_t item_str;
|
||||
uint8_t type;
|
||||
} SubGhzReceiverMenuItem;
|
||||
|
||||
ARRAY_DEF(SubGhzReceiverMenuItemArray, SubGhzReceiverMenuItem, M_POD_OPLIST)
|
||||
|
||||
#define M_OPL_SubGhzReceiverMenuItemArray_t() \
|
||||
ARRAY_OPLIST(SubGhzReceiverMenuItemArray, M_POD_OPLIST)
|
||||
|
||||
struct SubGhzReceiverHistory {
|
||||
SubGhzReceiverMenuItemArray_t data;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ReceiverSceneStart,
|
||||
ReceiverSceneMain,
|
||||
ReceiverSceneConfig,
|
||||
ReceiverSceneInfo,
|
||||
} SubghzReceiverScene;
|
||||
|
||||
typedef enum {
|
||||
SubGhzHopperStateOFF,
|
||||
SubGhzHopperStatePause,
|
||||
SubGhzHopperStateRunnig,
|
||||
SubGhzHopperStateRSSITimeOut,
|
||||
} SubGhzHopperState;
|
||||
typedef struct SubGhzReceiverHistory SubGhzReceiverHistory;
|
||||
|
||||
static const Icon* ReceiverItemIcons[] = {
|
||||
[TYPE_PROTOCOL_UNKNOWN] = &I_Quest_7x8,
|
||||
@ -48,27 +38,16 @@ struct SubghzReceiver {
|
||||
View* view;
|
||||
SubghzReceiverCallback callback;
|
||||
void* context;
|
||||
SubGhzWorker* worker;
|
||||
SubGhzProtocol* protocol;
|
||||
osTimerId timer;
|
||||
SubGhzHopperState hopper_state;
|
||||
uint8_t hopper_timeout;
|
||||
uint32_t event_key_sequence;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
string_t text;
|
||||
uint16_t scene;
|
||||
SubGhzProtocolCommon* protocol_result;
|
||||
SubGhzHistory* history;
|
||||
uint8_t frequency;
|
||||
uint8_t temp_frequency;
|
||||
uint32_t real_frequency;
|
||||
|
||||
string_t frequency_str;
|
||||
string_t preset_str;
|
||||
string_t history_stat_str;
|
||||
SubGhzReceiverHistory* history;
|
||||
uint16_t idx;
|
||||
uint16_t list_offset;
|
||||
uint16_t history_item;
|
||||
bool menu;
|
||||
} SubghzReceiverModel;
|
||||
|
||||
void subghz_receiver_set_callback(
|
||||
@ -81,35 +60,6 @@ void subghz_receiver_set_callback(
|
||||
subghz_receiver->context = context;
|
||||
}
|
||||
|
||||
void subghz_receiver_set_protocol(
|
||||
SubghzReceiver* subghz_receiver,
|
||||
SubGhzProtocolCommon* protocol_result,
|
||||
SubGhzProtocol* protocol) {
|
||||
furi_assert(subghz_receiver);
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
model->protocol_result = protocol_result;
|
||||
return true;
|
||||
});
|
||||
subghz_receiver->protocol = protocol;
|
||||
}
|
||||
|
||||
SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver) {
|
||||
furi_assert(subghz_receiver);
|
||||
SubGhzProtocolCommon* result = NULL;
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
result = model->protocol_result;
|
||||
return false;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker) {
|
||||
furi_assert(subghz_receiver);
|
||||
subghz_receiver->worker = worker;
|
||||
}
|
||||
|
||||
static void subghz_receiver_update_offset(SubghzReceiver* subghz_receiver) {
|
||||
furi_assert(subghz_receiver);
|
||||
|
||||
@ -129,6 +79,38 @@ static void subghz_receiver_update_offset(SubghzReceiver* subghz_receiver) {
|
||||
});
|
||||
}
|
||||
|
||||
void subghz_receiver_add_item_to_menu(
|
||||
SubghzReceiver* subghz_receiver,
|
||||
const char* name,
|
||||
uint8_t type) {
|
||||
furi_assert(subghz_receiver);
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
SubGhzReceiverMenuItem* item_menu =
|
||||
SubGhzReceiverMenuItemArray_push_raw(model->history->data);
|
||||
string_init_set_str(item_menu->item_str, name);
|
||||
item_menu->type = type;
|
||||
model->history_item++;
|
||||
return true;
|
||||
});
|
||||
subghz_receiver_update_offset(subghz_receiver);
|
||||
}
|
||||
|
||||
void subghz_receiver_add_data_statusbar(
|
||||
SubghzReceiver* subghz_receiver,
|
||||
const char* frequency_str,
|
||||
const char* preset_str,
|
||||
const char* history_stat_str) {
|
||||
furi_assert(subghz_receiver);
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
string_set(model->frequency_str, frequency_str);
|
||||
string_set(model->preset_str, preset_str);
|
||||
string_set(model->history_stat_str, history_stat_str);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
static void subghz_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT);
|
||||
@ -144,462 +126,113 @@ static void subghz_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scroll
|
||||
}
|
||||
|
||||
void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
|
||||
bool scrollbar = model->history_item > 4;
|
||||
string_t str_buff;
|
||||
char buffer[64];
|
||||
uint32_t frequency;
|
||||
string_init(str_buff);
|
||||
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
switch(model->scene) {
|
||||
case ReceiverSceneMain:
|
||||
for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) {
|
||||
size_t idx = CLAMP(i + model->list_offset, model->history_item, 0);
|
||||
subghz_history_get_text_item_menu(model->history, str_buff, idx);
|
||||
elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX);
|
||||
if(model->idx == idx) {
|
||||
subghz_receiver_draw_frame(canvas, i, scrollbar);
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
canvas_draw_icon(
|
||||
canvas,
|
||||
1,
|
||||
2 + i * FRAME_HEIGHT,
|
||||
ReceiverItemIcons[subghz_history_get_type_protocol(model->history, idx)]);
|
||||
canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, string_get_cstr(str_buff));
|
||||
string_clean(str_buff);
|
||||
}
|
||||
if(scrollbar) {
|
||||
elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item);
|
||||
}
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_button_left(canvas, "Config");
|
||||
|
||||
elements_button_left(canvas, "Config");
|
||||
canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
if(subghz_history_get_text_space_left(model->history, str_buff)) {
|
||||
canvas_draw_str(canvas, 54, 62, string_get_cstr(str_buff));
|
||||
} else {
|
||||
if((model->real_frequency / 1000 % 10) > 4) {
|
||||
frequency = model->real_frequency + 10000;
|
||||
} else {
|
||||
frequency = model->real_frequency;
|
||||
}
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"%03ld.%02ld",
|
||||
frequency / 1000000 % 1000,
|
||||
frequency / 10000 % 100);
|
||||
canvas_draw_str(canvas, 44, 62, buffer);
|
||||
canvas_draw_str(canvas, 79, 62, "AM");
|
||||
canvas_draw_str(canvas, 96, 62, string_get_cstr(str_buff));
|
||||
}
|
||||
break;
|
||||
|
||||
case ReceiverSceneStart:
|
||||
canvas_draw_str(canvas, 44, 62, string_get_cstr(model->frequency_str));
|
||||
canvas_draw_str(canvas, 79, 62, string_get_cstr(model->preset_str));
|
||||
canvas_draw_str(canvas, 96, 62, string_get_cstr(model->history_stat_str));
|
||||
if(model->history_item == 0) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 63, 46, "Scanning...");
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_button_left(canvas, "Config");
|
||||
if((model->real_frequency / 1000 % 10) > 4) {
|
||||
frequency = model->real_frequency + 10000;
|
||||
} else {
|
||||
frequency = model->real_frequency;
|
||||
}
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"%03ld.%02ld",
|
||||
frequency / 1000000 % 1000,
|
||||
frequency / 10000 % 100);
|
||||
canvas_draw_str(canvas, 44, 62, buffer);
|
||||
canvas_draw_str(canvas, 79, 62, "AM");
|
||||
subghz_history_get_text_space_left(model->history, str_buff);
|
||||
canvas_draw_str(canvas, 96, 62, string_get_cstr(str_buff));
|
||||
canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
break;
|
||||
|
||||
case ReceiverSceneConfig:
|
||||
if(model->frequency < subghz_frequencies_count) {
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"Frequency: < %03ld.%03ldMHz >",
|
||||
model->real_frequency / 1000000 % 1000,
|
||||
model->real_frequency / 1000 % 1000);
|
||||
canvas_draw_str(canvas, 0, 8, buffer);
|
||||
canvas_draw_str(canvas, 0, 18, "Frequency Hopping: <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;
|
||||
return;
|
||||
}
|
||||
canvas_draw_line(canvas, 46, 51, 125, 51);
|
||||
|
||||
bool scrollbar = model->history_item > 4;
|
||||
string_t str_buff;
|
||||
string_init(str_buff);
|
||||
|
||||
SubGhzReceiverMenuItem* item_menu;
|
||||
|
||||
for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) {
|
||||
size_t idx = CLAMP(i + model->list_offset, model->history_item, 0);
|
||||
item_menu = SubGhzReceiverMenuItemArray_get(model->history->data, idx);
|
||||
string_set(str_buff, item_menu->item_str);
|
||||
elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX);
|
||||
if(model->idx == idx) {
|
||||
subghz_receiver_draw_frame(canvas, i, scrollbar);
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
canvas_draw_icon(canvas, 1, 2 + i * FRAME_HEIGHT, ReceiverItemIcons[item_menu->type]);
|
||||
canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, string_get_cstr(str_buff));
|
||||
string_clean(str_buff);
|
||||
}
|
||||
if(scrollbar) {
|
||||
elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item);
|
||||
}
|
||||
string_clear(str_buff);
|
||||
}
|
||||
|
||||
void subghz_receiver_history_full(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzReceiver* subghz_receiver = context;
|
||||
subghz_receiver->callback(SubghzReceverEventSendHistoryFull, subghz_receiver->context);
|
||||
subghz_receiver->hopper_state = SubGhzHopperStateOFF;
|
||||
}
|
||||
|
||||
bool subghz_receiver_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
uint8_t scene = 0;
|
||||
SubghzReceiver* subghz_receiver = context;
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
scene = model->scene;
|
||||
return false;
|
||||
});
|
||||
|
||||
bool can_be_saved = false;
|
||||
|
||||
switch(scene) {
|
||||
case ReceiverSceneMain:
|
||||
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
model->idx = 0;
|
||||
model->list_offset = 0;
|
||||
model->history_item = 0;
|
||||
subghz_history_clean(model->history);
|
||||
return true;
|
||||
});
|
||||
return false;
|
||||
} else if(
|
||||
event->key == InputKeyUp &&
|
||||
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
if(model->idx != 0) model->idx--;
|
||||
return true;
|
||||
});
|
||||
} else if(
|
||||
event->key == InputKeyDown &&
|
||||
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
if(model->idx != subghz_history_get_item(model->history) - 1) model->idx++;
|
||||
return true;
|
||||
});
|
||||
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
||||
subghz_receiver->hopper_state = SubGhzHopperStatePause;
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
model->scene = ReceiverSceneConfig;
|
||||
model->temp_frequency = model->frequency;
|
||||
return true;
|
||||
});
|
||||
subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context);
|
||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||
subghz_receiver->event_key_sequence = event->sequence;
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
string_clean(model->text);
|
||||
model->protocol_result = subghz_protocol_get_by_name(
|
||||
subghz_receiver->protocol,
|
||||
subghz_history_get_name(model->history, model->idx));
|
||||
if(model->protocol_result->to_load_protocol != NULL) {
|
||||
model->protocol_result->to_load_protocol(
|
||||
model->protocol_result,
|
||||
subghz_history_get_raw_data(model->history, model->idx));
|
||||
model->protocol_result->to_string(model->protocol_result, model->text);
|
||||
model->scene = ReceiverSceneInfo;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case ReceiverSceneInfo:
|
||||
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||
subghz_receiver->callback(SubghzReceverEventBack, subghz_receiver->context);
|
||||
} else if(
|
||||
event->key == InputKeyUp &&
|
||||
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
can_be_saved =
|
||||
(model->protocol_result && model->protocol_result->to_save_string &&
|
||||
strcmp(model->protocol_result->name, "KeeLoq"));
|
||||
return false;
|
||||
if(model->idx != 0) model->idx--;
|
||||
return true;
|
||||
});
|
||||
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
subghz_rx_end(subghz_receiver->worker);
|
||||
model->real_frequency =
|
||||
subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]);
|
||||
subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
|
||||
model->scene = ReceiverSceneMain;
|
||||
return true;
|
||||
});
|
||||
subghz_receiver->callback(SubghzReceverEventMain, subghz_receiver->context);
|
||||
} else if(can_be_saved && event->key == InputKeyRight) {
|
||||
subghz_receiver->callback(SubghzReceverEventSave, subghz_receiver->context);
|
||||
return false;
|
||||
} else if(
|
||||
can_be_saved && event->key == InputKeyOk && event->type == InputTypePress &&
|
||||
subghz_receiver->event_key_sequence != event->sequence) {
|
||||
subghz_receiver->hopper_state = SubGhzHopperStatePause;
|
||||
subghz_rx_end(subghz_receiver->worker);
|
||||
subghz_receiver->callback(SubghzReceverEventSendStart, subghz_receiver->context);
|
||||
return true;
|
||||
} else if(
|
||||
can_be_saved && event->key == InputKeyOk && event->type == InputTypeRelease &&
|
||||
subghz_receiver->event_key_sequence != event->sequence) {
|
||||
subghz_receiver->callback(SubghzReceverEventSendStop, subghz_receiver->context);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case ReceiverSceneConfig:
|
||||
if(event->type != InputTypeShort) return false;
|
||||
if(event->key == InputKeyBack) {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
model->frequency = model->temp_frequency;
|
||||
model->real_frequency = subghz_frequencies[model->frequency];
|
||||
subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
|
||||
if(subghz_history_get_item(model->history) == 0) {
|
||||
model->scene = ReceiverSceneStart;
|
||||
} else {
|
||||
model->scene = ReceiverSceneMain;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
subghz_receiver->callback(SubghzReceverEventMain, subghz_receiver->context);
|
||||
} else if(event->key == InputKeyOk) {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
if(model->frequency < subghz_frequencies_count) {
|
||||
subghz_rx_end(subghz_receiver->worker);
|
||||
model->real_frequency = subghz_rx(
|
||||
subghz_receiver->worker, subghz_frequencies[model->frequency]);
|
||||
subghz_receiver->hopper_state = SubGhzHopperStateOFF;
|
||||
} else {
|
||||
osTimerStart(subghz_receiver->timer, 1024 / 10);
|
||||
subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
|
||||
}
|
||||
if(subghz_history_get_item(model->history) == 0) {
|
||||
model->scene = ReceiverSceneStart;
|
||||
} else {
|
||||
model->scene = ReceiverSceneMain;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
subghz_receiver->callback(SubghzReceverEventMain, subghz_receiver->context);
|
||||
} else {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
bool model_updated = false;
|
||||
|
||||
if(event->key == InputKeyLeft) {
|
||||
if(model->frequency > 0) model->frequency--;
|
||||
model_updated = true;
|
||||
} else if(event->key == InputKeyRight) {
|
||||
if(model->frequency < subghz_frequencies_count) model->frequency++;
|
||||
model_updated = true;
|
||||
}
|
||||
if(model_updated) {
|
||||
model->real_frequency = subghz_frequencies[model->frequency];
|
||||
}
|
||||
return model_updated;
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case ReceiverSceneStart:
|
||||
if(event->type != InputTypeShort) return false;
|
||||
if(event->key == InputKeyBack) {
|
||||
return false;
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
subghz_receiver->hopper_state = SubGhzHopperStatePause;
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
model->temp_frequency = model->frequency;
|
||||
model->scene = ReceiverSceneConfig;
|
||||
return true;
|
||||
});
|
||||
subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
subghz_receiver_update_offset(subghz_receiver);
|
||||
if(scene != ReceiverSceneInfo) {
|
||||
} else if(
|
||||
event->key == InputKeyDown &&
|
||||
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
if(subghz_history_get_text_space_left(model->history, NULL)) {
|
||||
subghz_receiver_history_full(subghz_receiver);
|
||||
if(model->idx != model->history_item - 1) model->idx++;
|
||||
return true;
|
||||
});
|
||||
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
||||
subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context);
|
||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
if(model->history_item != 0) {
|
||||
subghz_receiver->callback(SubghzReceverEventOK, subghz_receiver->context);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
subghz_receiver_update_offset(subghz_receiver);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_receiver_text_callback(string_t text, void* context) {
|
||||
furi_assert(context);
|
||||
SubghzReceiver* subghz_receiver = context;
|
||||
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
string_set(model->text, text);
|
||||
model->scene = ReceiverSceneMain;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void subghz_receiver_protocol_callback(SubGhzProtocolCommon* parser, void* context) {
|
||||
furi_assert(context);
|
||||
SubghzReceiver* subghz_receiver = context;
|
||||
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
model->protocol_result = parser;
|
||||
subghz_history_set_frequency_preset(
|
||||
model->history,
|
||||
model->history_item,
|
||||
model->real_frequency,
|
||||
FuriHalSubGhzPresetOok650Async);
|
||||
subghz_history_add_to_history(model->history, parser);
|
||||
|
||||
model->history_item = subghz_history_get_item(model->history);
|
||||
model->scene = ReceiverSceneMain;
|
||||
if(subghz_history_get_text_space_left(model->history, NULL)) {
|
||||
subghz_receiver_history_full(subghz_receiver);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
subghz_protocol_reset(subghz_receiver->protocol);
|
||||
subghz_receiver_update_offset(subghz_receiver);
|
||||
}
|
||||
|
||||
static void subghz_receiver_timer_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzReceiver* subghz_receiver = context;
|
||||
|
||||
switch(subghz_receiver->hopper_state) {
|
||||
case SubGhzHopperStatePause:
|
||||
return;
|
||||
break;
|
||||
case SubGhzHopperStateOFF:
|
||||
osTimerStop(subghz_receiver->timer);
|
||||
return;
|
||||
break;
|
||||
case SubGhzHopperStateRSSITimeOut:
|
||||
if(subghz_receiver->hopper_timeout != 0) {
|
||||
subghz_receiver->hopper_timeout--;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
float rssi = -127.0f;
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
if(subghz_receiver->hopper_state != SubGhzHopperStateRSSITimeOut) {
|
||||
// See RSSI Calculation timings in CC1101 17.3 RSSI
|
||||
rssi = furi_hal_subghz_get_rssi();
|
||||
|
||||
// Stay if RSSI is high enough
|
||||
if(rssi > -90.0f) {
|
||||
subghz_receiver->hopper_timeout = 10;
|
||||
subghz_receiver->hopper_state = SubGhzHopperStateRSSITimeOut;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
|
||||
}
|
||||
|
||||
// Select next frequency
|
||||
if(model->frequency < COUNT_FREQUNCY_HOPPER - 1) {
|
||||
model->frequency++;
|
||||
} else {
|
||||
model->frequency = 0;
|
||||
}
|
||||
|
||||
// Restart radio
|
||||
furi_hal_subghz_idle();
|
||||
subghz_protocol_reset(subghz_receiver->protocol);
|
||||
model->real_frequency = furi_hal_subghz_set_frequency_and_path(
|
||||
subghz_frequencies_hopper[model->frequency]);
|
||||
furi_hal_subghz_rx();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void subghz_receiver_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzReceiver* subghz_receiver = context;
|
||||
//Start CC1101 Rx
|
||||
subghz_begin(FuriHalSubGhzPresetOok650Async);
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
subghz_rx_end(subghz_receiver->worker);
|
||||
model->frequency = subghz_frequencies_433_92;
|
||||
model->real_frequency =
|
||||
subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]);
|
||||
if(subghz_history_get_item(model->history) == 0) {
|
||||
model->scene = ReceiverSceneStart;
|
||||
} else {
|
||||
model->scene = ReceiverSceneMain;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
subghz_protocol_enable_dump(
|
||||
subghz_receiver->protocol, subghz_receiver_protocol_callback, subghz_receiver);
|
||||
//SubghzReceiver* subghz_receiver = context;
|
||||
}
|
||||
|
||||
void subghz_receiver_exit(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzReceiver* subghz_receiver = context;
|
||||
osTimerStop(subghz_receiver->timer);
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
string_clean(model->text);
|
||||
return true;
|
||||
string_clean(model->frequency_str);
|
||||
string_clean(model->preset_str);
|
||||
string_clean(model->history_stat_str);
|
||||
for
|
||||
M_EACH(item_menu, model->history->data, SubGhzReceiverMenuItemArray_t) {
|
||||
string_clear(item_menu->item_str);
|
||||
item_menu->type = 0;
|
||||
}
|
||||
SubGhzReceiverMenuItemArray_clean(model->history->data);
|
||||
model->idx = 0;
|
||||
model->list_offset = 0;
|
||||
model->history_item = 0;
|
||||
return false;
|
||||
});
|
||||
// Stop CC1101 Rx
|
||||
subghz_rx_end(subghz_receiver->worker);
|
||||
subghz_sleep();
|
||||
}
|
||||
|
||||
SubghzReceiver* subghz_receiver_alloc() {
|
||||
@ -616,14 +249,14 @@ SubghzReceiver* subghz_receiver_alloc() {
|
||||
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
string_init(model->text);
|
||||
model->history = subghz_history_alloc();
|
||||
string_init(model->frequency_str);
|
||||
string_init(model->preset_str);
|
||||
string_init(model->history_stat_str);
|
||||
model->history = furi_alloc(sizeof(SubGhzReceiverHistory));
|
||||
SubGhzReceiverMenuItemArray_init(model->history->data);
|
||||
return true;
|
||||
});
|
||||
|
||||
subghz_receiver->timer =
|
||||
osTimerNew(subghz_receiver_timer_callback, osTimerPeriodic, subghz_receiver, NULL);
|
||||
subghz_receiver->hopper_state = SubGhzHopperStateOFF;
|
||||
return subghz_receiver;
|
||||
}
|
||||
|
||||
@ -632,11 +265,18 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver) {
|
||||
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
string_clear(model->text);
|
||||
subghz_history_free(model->history);
|
||||
return false;
|
||||
string_clear(model->frequency_str);
|
||||
string_clear(model->preset_str);
|
||||
string_clear(model->history_stat_str);
|
||||
for
|
||||
M_EACH(item_menu, model->history->data, SubGhzReceiverMenuItemArray_t) {
|
||||
string_clear(item_menu->item_str);
|
||||
item_menu->type = 0;
|
||||
}
|
||||
SubGhzReceiverMenuItemArray_clear(model->history->data);
|
||||
free(model->history);
|
||||
return false;
|
||||
});
|
||||
osTimerDelete(subghz_receiver->timer);
|
||||
view_free(subghz_receiver->view);
|
||||
free(subghz_receiver);
|
||||
}
|
||||
@ -646,43 +286,24 @@ View* subghz_receiver_get_view(SubghzReceiver* subghz_receiver) {
|
||||
return subghz_receiver->view;
|
||||
}
|
||||
|
||||
uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver) {
|
||||
uint16_t subghz_receiver_get_idx_menu(SubghzReceiver* subghz_receiver) {
|
||||
furi_assert(subghz_receiver);
|
||||
uint32_t frequency;
|
||||
uint32_t idx = 0;
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
frequency = subghz_history_get_frequency(model->history, model->idx);
|
||||
idx = model->idx;
|
||||
return false;
|
||||
});
|
||||
return frequency;
|
||||
return idx;
|
||||
}
|
||||
|
||||
FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver) {
|
||||
void subghz_receiver_set_idx_menu(SubghzReceiver* subghz_receiver, uint16_t idx) {
|
||||
furi_assert(subghz_receiver);
|
||||
FuriHalSubGhzPreset preset;
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
preset = subghz_history_get_preset(model->history, model->idx);
|
||||
return false;
|
||||
model->idx = idx;
|
||||
if(model->idx > 2) model->list_offset = idx - 2;
|
||||
return true;
|
||||
});
|
||||
return preset;
|
||||
}
|
||||
|
||||
void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output) {
|
||||
furi_assert(subghz_receiver);
|
||||
uint32_t frequency;
|
||||
uint32_t preset;
|
||||
with_view_model(
|
||||
subghz_receiver->view, (SubghzReceiverModel * model) {
|
||||
frequency = subghz_history_get_frequency(model->history, model->idx);
|
||||
preset = (uint32_t)subghz_history_get_preset(model->history, model->idx);
|
||||
return false;
|
||||
});
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Frequency: %d\n"
|
||||
"Preset: %d\n",
|
||||
(int)frequency,
|
||||
(int)preset);
|
||||
subghz_receiver_update_offset(subghz_receiver);
|
||||
}
|
@ -1,21 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#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 {
|
||||
SubghzReceverEventOK,
|
||||
SubghzReceverEventConfig,
|
||||
SubghzReceverEventMain,
|
||||
SubghzReceverEventSave,
|
||||
SubghzReceverEventBack,
|
||||
SubghzReceverEventMore,
|
||||
SubghzReceverEventSendStart,
|
||||
SubghzReceverEventSendStop,
|
||||
SubghzReceverEventSendHistoryFull,
|
||||
} SubghzReceverEvent;
|
||||
|
||||
typedef struct SubghzReceiver SubghzReceiver;
|
||||
@ -33,17 +23,19 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver);
|
||||
|
||||
View* subghz_receiver_get_view(SubghzReceiver* subghz_receiver);
|
||||
|
||||
void subghz_receiver_set_protocol(
|
||||
void subghz_receiver_add_data_statusbar(
|
||||
SubghzReceiver* subghz_receiver,
|
||||
SubGhzProtocolCommon* protocol_result,
|
||||
SubGhzProtocol* protocol);
|
||||
const char* frequency_str,
|
||||
const char* preset_str,
|
||||
const char* history_stat_str);
|
||||
|
||||
SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver);
|
||||
void subghz_receiver_add_item_to_menu(
|
||||
SubghzReceiver* subghz_receiver,
|
||||
const char* name,
|
||||
uint8_t type);
|
||||
|
||||
void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker);
|
||||
uint16_t subghz_receiver_get_idx_menu(SubghzReceiver* subghz_receiver);
|
||||
|
||||
uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver);
|
||||
void subghz_receiver_set_idx_menu(SubghzReceiver* subghz_receiver, uint16_t idx);
|
||||
|
||||
FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver);
|
||||
|
||||
void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output);
|
||||
void subghz_receiver_exit(void* context);
|
@ -1,13 +1,8 @@
|
||||
#include "subghz_transmitter.h"
|
||||
#include "../subghz_i.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <notification/notification-messages.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_keeloq.h>
|
||||
|
||||
struct SubghzTransmitter {
|
||||
View* view;
|
||||
@ -16,11 +11,10 @@ struct SubghzTransmitter {
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
string_t text;
|
||||
uint16_t scene;
|
||||
uint32_t real_frequency;
|
||||
FuriHalSubGhzPreset preset;
|
||||
SubGhzProtocolCommon* protocol;
|
||||
string_t frequency_str;
|
||||
string_t preset_str;
|
||||
string_t key_str;
|
||||
uint8_t show_button;
|
||||
} SubghzTransmitterModel;
|
||||
|
||||
void subghz_transmitter_set_callback(
|
||||
@ -33,24 +27,19 @@ void subghz_transmitter_set_callback(
|
||||
subghz_transmitter->context = context;
|
||||
}
|
||||
|
||||
void subghz_transmitter_set_protocol(
|
||||
void subghz_transmitter_add_data_to_show(
|
||||
SubghzTransmitter* subghz_transmitter,
|
||||
SubGhzProtocolCommon* protocol) {
|
||||
const char* key_str,
|
||||
const char* frequency_str,
|
||||
const char* preset_str,
|
||||
uint8_t show_button) {
|
||||
furi_assert(subghz_transmitter);
|
||||
with_view_model(
|
||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||
model->protocol = protocol;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void subghz_transmitter_set_frequency_preset(
|
||||
SubghzTransmitter* subghz_transmitter,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset) {
|
||||
with_view_model(
|
||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||
model->real_frequency = frequency;
|
||||
model->preset = preset;
|
||||
string_set(model->key_str, key_str);
|
||||
string_set(model->frequency_str, frequency_str);
|
||||
string_set(model->preset_str, preset_str);
|
||||
model->show_button = show_button;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@ -87,26 +76,13 @@ static void subghz_transmitter_button_right(Canvas* canvas, const char* str) {
|
||||
}
|
||||
|
||||
void subghz_transmitter_draw(Canvas* canvas, SubghzTransmitterModel* model) {
|
||||
char buffer[64];
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text(canvas, 0, 8, string_get_cstr(model->text));
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"%03ld.%03ld",
|
||||
model->real_frequency / 1000000 % 1000,
|
||||
model->real_frequency / 1000 % 1000);
|
||||
canvas_draw_str(canvas, 90, 8, buffer);
|
||||
|
||||
if(model->protocol && model->protocol->get_upload_protocol) {
|
||||
if((!strcmp(model->protocol->name, "KeeLoq")) &&
|
||||
(!strcmp(subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) {
|
||||
return;
|
||||
}
|
||||
subghz_transmitter_button_right(canvas, "Send");
|
||||
}
|
||||
elements_multiline_text(canvas, 0, 8, string_get_cstr(model->key_str));
|
||||
canvas_draw_str(canvas, 78, 8, string_get_cstr(model->frequency_str));
|
||||
canvas_draw_str(canvas, 113, 8, string_get_cstr(model->preset_str));
|
||||
if(model->show_button) subghz_transmitter_button_right(canvas, "Send");
|
||||
}
|
||||
|
||||
bool subghz_transmitter_input(InputEvent* event, void* context) {
|
||||
@ -114,26 +90,25 @@ bool subghz_transmitter_input(InputEvent* event, void* context) {
|
||||
SubghzTransmitter* subghz_transmitter = context;
|
||||
bool can_be_sent = false;
|
||||
|
||||
if(event->key == InputKeyBack) {
|
||||
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||
string_clean(model->frequency_str);
|
||||
string_clean(model->preset_str);
|
||||
string_clean(model->key_str);
|
||||
model->show_button = 0;
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
with_view_model(
|
||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||
if(model->protocol && model->protocol->get_upload_protocol) {
|
||||
if((!strcmp(model->protocol->name, "KeeLoq")) &&
|
||||
(!strcmp(
|
||||
subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) {
|
||||
return false;
|
||||
}
|
||||
if(model->show_button) {
|
||||
can_be_sent = true;
|
||||
}
|
||||
//can_be_sent = (model->protocol && model->protocol->get_upload_protocol);
|
||||
string_clean(model->text);
|
||||
model->protocol->to_string(model->protocol, model->text);
|
||||
return true;
|
||||
});
|
||||
//if(event->type != InputTypeShort) return false;
|
||||
|
||||
if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) {
|
||||
subghz_transmitter->callback(SubghzTransmitterEventSendStart, subghz_transmitter->context);
|
||||
@ -146,37 +121,14 @@ bool subghz_transmitter_input(InputEvent* event, void* context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_transmitter_text_callback(string_t text, void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTransmitter* subghz_transmitter = context;
|
||||
|
||||
with_view_model(
|
||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||
string_set(model->text, text);
|
||||
model->scene = 0;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void subghz_transmitter_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTransmitter* subghz_transmitter = context;
|
||||
with_view_model(
|
||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||
string_clean(model->text);
|
||||
model->protocol->to_string(model->protocol, model->text);
|
||||
return true;
|
||||
});
|
||||
// SubghzTransmitter* subghz_transmitter = context;
|
||||
}
|
||||
|
||||
void subghz_transmitter_exit(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTransmitter* subghz_transmitter = context;
|
||||
with_view_model(
|
||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||
string_clean(model->text);
|
||||
return true;
|
||||
});
|
||||
// SubghzTransmitter* subghz_transmitter = context;
|
||||
}
|
||||
|
||||
SubghzTransmitter* subghz_transmitter_alloc() {
|
||||
@ -194,7 +146,9 @@ SubghzTransmitter* subghz_transmitter_alloc() {
|
||||
|
||||
with_view_model(
|
||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||
string_init(model->text);
|
||||
string_init(model->frequency_str);
|
||||
string_init(model->preset_str);
|
||||
string_init(model->key_str);
|
||||
return true;
|
||||
});
|
||||
return subghz_transmitter;
|
||||
@ -205,7 +159,9 @@ void subghz_transmitter_free(SubghzTransmitter* subghz_transmitter) {
|
||||
|
||||
with_view_model(
|
||||
subghz_transmitter->view, (SubghzTransmitterModel * model) {
|
||||
string_clear(model->text);
|
||||
string_clear(model->frequency_str);
|
||||
string_clear(model->preset_str);
|
||||
string_clear(model->key_str);
|
||||
return true;
|
||||
});
|
||||
view_free(subghz_transmitter->view);
|
||||
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
||||
|
||||
typedef enum {
|
||||
SubghzTransmitterEventSendStart,
|
||||
@ -25,10 +24,9 @@ void subghz_transmitter_free(SubghzTransmitter* subghz_transmitter);
|
||||
|
||||
View* subghz_transmitter_get_view(SubghzTransmitter* subghz_transmitter);
|
||||
|
||||
void subghz_transmitter_set_protocol(
|
||||
void subghz_transmitter_add_data_to_show(
|
||||
SubghzTransmitter* subghz_transmitter,
|
||||
SubGhzProtocolCommon* protocol);
|
||||
void subghz_transmitter_set_frequency_preset(
|
||||
SubghzTransmitter* subghz_transmitter,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset);
|
||||
const char* key_str,
|
||||
const char* frequency_str,
|
||||
const char* preset_str,
|
||||
uint8_t show_button);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "subghz_protocol_faac_slh.h"
|
||||
#include "subghz_protocol_nero_sketch.h"
|
||||
#include "subghz_protocol_star_line.h"
|
||||
#include "subghz_protocol_nero_radio.h"
|
||||
|
||||
#include "../subghz_keystore.h"
|
||||
|
||||
@ -27,6 +28,7 @@ typedef enum {
|
||||
SubGhzProtocolTypeFaacSLH,
|
||||
SubGhzProtocolTypeNeroSketch,
|
||||
SubGhzProtocolTypeStarLine,
|
||||
SubGhzProtocolTypeNeroRadio,
|
||||
|
||||
SubGhzProtocolTypeMax,
|
||||
} SubGhzProtocolType;
|
||||
@ -88,6 +90,8 @@ SubGhzProtocol* subghz_protocol_alloc() {
|
||||
(SubGhzProtocolCommon*)subghz_protocol_nero_sketch_alloc();
|
||||
instance->protocols[SubGhzProtocolTypeStarLine] =
|
||||
(SubGhzProtocolCommon*)subghz_protocol_star_line_alloc(instance->keystore);
|
||||
instance->protocols[SubGhzProtocolTypeNeroRadio] =
|
||||
(SubGhzProtocolCommon*)subghz_protocol_nero_radio_alloc();
|
||||
|
||||
return instance;
|
||||
}
|
||||
@ -113,6 +117,8 @@ void subghz_protocol_free(SubGhzProtocol* instance) {
|
||||
(SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]);
|
||||
subghz_protocol_star_line_free(
|
||||
(SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]);
|
||||
subghz_protocol_nero_radio_free(
|
||||
(SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio]);
|
||||
|
||||
subghz_keystore_free(instance->keystore);
|
||||
|
||||
@ -163,7 +169,6 @@ void subghz_protocol_enable_dump(
|
||||
}
|
||||
|
||||
void subghz_protocol_load_nice_flor_s_file(SubGhzProtocol* instance, const char* file_name) {
|
||||
// subghz_protocol_nice_flor_s_name_file(instance->nice_flor_s, file_name);
|
||||
subghz_protocol_nice_flor_s_name_file(
|
||||
(SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name);
|
||||
}
|
||||
@ -191,6 +196,8 @@ void subghz_protocol_reset(SubGhzProtocol* instance) {
|
||||
(SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]);
|
||||
subghz_protocol_star_line_reset(
|
||||
(SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]);
|
||||
subghz_protocol_nero_radio_reset(
|
||||
(SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio]);
|
||||
}
|
||||
|
||||
void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration) {
|
||||
@ -220,4 +227,8 @@ void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t durati
|
||||
duration);
|
||||
subghz_protocol_star_line_parse(
|
||||
(SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine], level, duration);
|
||||
subghz_protocol_nero_radio_parse(
|
||||
(SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio],
|
||||
level,
|
||||
duration);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param instance - SubGhzProtocolGateTX instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -398,9 +398,9 @@ void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t outp
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%lX\r\n"
|
||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||
"Key:%08lX%08lX\r\n"
|
||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||
"MF:%s\r\n"
|
||||
"Sn:0x%07lX \r\n",
|
||||
instance->common.name,
|
||||
|
@ -49,7 +49,7 @@ uint64_t subghz_protocol_keeloq_gen_key(void* context);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param instance - SubGhzProtocolKeeloq instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
|
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
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param instance - SubGhzProtocolNeroSketch instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -18,7 +18,7 @@ void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance);
|
||||
|
||||
/** Get upload protocol
|
||||
*
|
||||
* @param instance - SubGhzProtocolCame instance
|
||||
* @param instance - SubGhzProtocolNiceFlo instance
|
||||
* @param encoder - SubGhzProtocolCommonEncoder encoder
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -172,7 +172,7 @@ void subghz_decoder_princeton_parse(
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = 1;
|
||||
if(instance->common.code_count_bit >=
|
||||
if(instance->common.code_count_bit ==
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found == instance->common.code_found) {
|
||||
//instance->te = (instance->te+instance->common.te_last)/2; //Option 1 TE averaging
|
||||
|
@ -282,9 +282,9 @@ void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%lX\r\n"
|
||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||
"Key:%08lX%08lX\r\n"
|
||||
"Fix:0x%08lX Cnt:%04X\r\n"
|
||||
"Hop:0x%08lX Btn:%02lX\r\n"
|
||||
"MF:%s\r\n"
|
||||
"Sn:0x%07lX \r\n",
|
||||
instance->common.name,
|
||||
|
Loading…
Reference in New Issue
Block a user