[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:
Skorpionm
2021-09-10 04:29:57 +04:00
committed by GitHub
parent fbccb9fbaf
commit f385340b2e
34 changed files with 1493 additions and 801 deletions

View File

@@ -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)

View File

@@ -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;

View 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);
}

View 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);
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}