diff options
author | Skorpionm <85568270+Skorpionm@users.noreply.github.com> | 2021-08-28 16:51:48 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-28 16:51:48 +0300 |
commit | 0a8a944e100c79432773ef3b6e749ab065e46cd1 (patch) | |
tree | ddde4e2a185a517a021431958d3b46af6fe139da /applications/subghz | |
parent | c3a1836fcd67d0511f8c186afd5ffdfa9f3f699e (diff) |
Skorp subghz signal archive (#667)
* SubGhz: Add millis() furi, add subghz history struct
* SubGhz: Fix subghz history
* Gubghz: Fix code repeat history, add clean history
* SubGhz: reading and adding keys to history
* Gui: Renaming Sub 1-Ghz -> SubGhz
* Archive: Renaming Sub 1-Ghz -> SubGhz
* SubGhz: Add menu history, modified button for sending a signal, changed output of data about accepted protocol
* Archive: Fix name subghz
* SubGhz: Menu navigation
* Assets: Add assets/SubGHz/icon.png
* Assets: add new icons for subghz
* SubGhz: Fix name Add manually scene
* SubGhz: Fix load icon Read scene. rename encoder struct, rename protocol function load from file, add load raw data protocol, add info pleasant signals all protocol
* SubGhz: fix memory leak
* SubGhz: change of receiving frequency for read scene
* SubGhz: Add save/load frequency and preset, add automatic configuration of transmit/receive to the desired frequency and modulation, add button "save" config scene
* SubGhz: Fix frequency and preset, fix frequency add manualli scene, fix re-executing the parser
* Furi-hal-subghz: add 2-FSK config, fix ook config 650KHz BW Tx filter
* Fix formatting and release build
* SubGhz: Delete read scene
* SubGhz: Fix frequency add manualli scene, refactoring code
* SubGhz: 2 profiles for OOK, fix broken build.
* SubGhz: Add passing static codes from read scene, add notification read scene, refactoring code
* SubGhz: fix assert on worker double stop.
Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Diffstat (limited to 'applications/subghz')
21 files changed, 859 insertions, 139 deletions
diff --git a/applications/subghz/scenes/subghz_scene_config.h b/applications/subghz/scenes/subghz_scene_config.h index 460001d2..514abd38 100644 --- a/applications/subghz/scenes/subghz_scene_config.h +++ b/applications/subghz/scenes/subghz_scene_config.h @@ -1,6 +1,5 @@ ADD_SCENE(subghz, start, Start) ADD_SCENE(subghz, analyze, Analyze) -ADD_SCENE(subghz, read, Read) ADD_SCENE(subghz, receiver, Receiver) ADD_SCENE(subghz, save_name, SaveName) ADD_SCENE(subghz, save_success, SaveSuccess) diff --git a/applications/subghz/scenes/subghz_scene_read.c b/applications/subghz/scenes/subghz_scene_read.c deleted file mode 100644 index 7cab340d..00000000 --- a/applications/subghz/scenes/subghz_scene_read.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "../subghz_i.h" - -#define GUBGHZ_READ_CUSTOM_EVENT (10UL) - -void subghz_read_protocol_callback(SubGhzProtocolCommon* parser, void* context) { - furi_assert(context); - SubGhz* subghz = context; - subghz->protocol_result = parser; - view_dispatcher_send_custom_event(subghz->view_dispatcher, GUBGHZ_READ_CUSTOM_EVENT); -} -void subghz_scene_read_callback(DialogExResult result, void* context) { - SubGhz* subghz = context; - view_dispatcher_send_custom_event(subghz->view_dispatcher, result); -} - -const void subghz_scene_read_on_enter(void* context) { - SubGhz* subghz = context; - - // Setup view - DialogEx* dialog_ex = subghz->dialog_ex; - - dialog_ex_set_header(dialog_ex, "SubGhz 433.92", 36, 6, AlignLeft, AlignCenter); - dialog_ex_set_icon(dialog_ex, 10, 12, &I_RFIDDolphinReceive_97x61); - - //Start CC1101 rx - subghz_begin(FuriHalSubGhzPresetOokAsync); - subghz_rx(433920000); - - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, subghz->worker); - subghz_worker_start(subghz->worker); - subghz_protocol_enable_dump(subghz->protocol, subghz_read_protocol_callback, subghz); - - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewDialogEx); -} - -const bool subghz_scene_read_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GUBGHZ_READ_CUSTOM_EVENT) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); - notification_message(subghz->notifications, &sequence_success); - return true; - } - } else if(event.type == SceneManagerEventTypeTick) { - notification_message(subghz->notifications, &sequence_blink_blue_10); - return true; - } - return false; -} - -const void subghz_scene_read_on_exit(void* context) { - SubGhz* subghz = context; - - // Stop CC1101 - subghz_worker_stop(subghz->worker); - furi_hal_subghz_stop_async_rx(); - subghz_end(); - - DialogEx* dialog_ex = subghz->dialog_ex; - dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); - dialog_ex_set_icon(dialog_ex, 0, 0, NULL); -} diff --git a/applications/subghz/scenes/subghz_scene_receiver.c b/applications/subghz/scenes/subghz_scene_receiver.c index 1fe9a466..f0607f17 100644 --- a/applications/subghz/scenes/subghz_scene_receiver.c +++ b/applications/subghz/scenes/subghz_scene_receiver.c @@ -13,7 +13,9 @@ const void subghz_scene_receiver_on_enter(void* context) { subghz_receiver_set_callback(subghz_receiver, subghz_scene_receiver_callback, subghz); - subghz_receiver_set_protocol(subghz_receiver, subghz->protocol_result); + 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; view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewReceiver); } @@ -21,12 +23,53 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubghzReceverEventSave) { + 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; - } else if(event.event == SubghzReceverEventBack) { + break; + case SubghzReceverEventBack: scene_manager_previous_scene(subghz->scene_manager); 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; + return true; + break; + case SubghzReceverEventConfig: + subghz->state_notifications = NOTIFICATION_IDLE_STATE; + return true; + break; + default: + break; + } + } else if(event.type == SceneManagerEventTypeTick) { + 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; diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c index 5a3452f8..fba0c622 100644 --- a/applications/subghz/scenes/subghz_scene_save_name.c +++ b/applications/subghz/scenes/subghz_scene_save_name.c @@ -19,7 +19,7 @@ const void subghz_scene_save_name_on_enter(void* context) { set_random_name(subghz->text_store, sizeof(subghz->text_store)); dev_name_empty = true; - text_input_set_header_text(text_input, "Name the KEY"); + text_input_set_header_text(text_input, "Name signal"); text_input_set_result_callback( text_input, subghz_scene_save_name_text_input_callback, diff --git a/applications/subghz/scenes/subghz_scene_saved.c b/applications/subghz/scenes/subghz_scene_saved.c index 09b7a4ac..3bfec82a 100644 --- a/applications/subghz/scenes/subghz_scene_saved.c +++ b/applications/subghz/scenes/subghz_scene_saved.c @@ -3,7 +3,7 @@ const void subghz_scene_saved_on_enter(void* context) { SubGhz* subghz = context; - if(subghz_saved_protocol_select(subghz)) { + if(subghz_load_protocol_from_file(subghz)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTransmitter); } else { scene_manager_search_and_switch_to_previous_scene(subghz->scene_manager, SubGhzSceneStart); diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/subghz/scenes/subghz_scene_set_type.c index d3c36f54..8948f06e 100644 --- a/applications/subghz/scenes/subghz_scene_set_type.c +++ b/applications/subghz/scenes/subghz_scene_set_type.c @@ -32,31 +32,31 @@ const void subghz_scene_set_type_on_enter(void* context) { submenu_add_item( subghz->submenu, - "Pricenton", + "Princeton_433", SubmenuIndexPricenton, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "Nice Flo 12bit", + "Nice Flo 12bit_433", SubmenuIndexNiceFlo12bit, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "Nice Flo 24bit", + "Nice Flo 24bit_433", SubmenuIndexNiceFlo24bit, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "CAME 12bit", + "CAME 12bit_433", SubmenuIndexCAME12bit, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "CAME 24bit", + "CAME 24bit_433", SubmenuIndexCAME24bit, subghz_scene_set_type_submenu_callback, subghz); @@ -64,13 +64,13 @@ const void subghz_scene_set_type_on_enter(void* context) { // subghz->submenu, "Nero Sketch", SubmenuIndexNeroSketch, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "Gate TX", + "Gate TX_433", SubmenuIndexGateTX, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "DoorHan", + "DoorHan_433", SubmenuIndexDoorHan, subghz_scene_set_type_submenu_callback, subghz); @@ -159,6 +159,8 @@ const bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event break; } if(generated_protocol) { + subghz->frequency = subghz_frequencies[subghz_frequencies_433_92]; + subghz->preset = FuriHalSubGhzPresetOok650Async; scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); return true; } diff --git a/applications/subghz/scenes/subghz_scene_start.c b/applications/subghz/scenes/subghz_scene_start.c index d30536a5..64e50d6a 100644 --- a/applications/subghz/scenes/subghz_scene_start.c +++ b/applications/subghz/scenes/subghz_scene_start.c @@ -56,9 +56,12 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneAnalyze); return true; } else if(event.event == SubmenuIndexRead) { + // scene_manager_set_scene_state( + // subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead); + // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRead); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRead); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); return true; } else if(event.event == SubmenuIndexSaved) { scene_manager_set_scene_state( diff --git a/applications/subghz/scenes/subghz_scene_transmitter.c b/applications/subghz/scenes/subghz_scene_transmitter.c index e28e6d88..3ce3ad2d 100644 --- a/applications/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/subghz/scenes/subghz_scene_transmitter.c @@ -13,6 +13,7 @@ const void subghz_scene_transmitter_on_enter(void* context) { 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); @@ -30,6 +31,7 @@ const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent ev } else if(event.event == SubghzTransmitterEventSendStop) { subghz->state_notifications = NOTIFICATION_IDLE_STATE; subghz_transmitter_tx_stop(subghz); + subghz_sleep(); return true; } else if(event.event == SubghzTransmitterEventBack) { subghz->state_notifications = NOTIFICATION_IDLE_STATE; diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index 0e4eb7fe..3031fec1 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -42,7 +42,7 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { } furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); @@ -79,7 +79,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { } furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); printf("Receiving at frequency %lu Hz\r\n", frequency); printf("Press CTRL+C to stop\r\n"); @@ -134,12 +134,12 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { protocol->common.code_last_found = key; protocol->common.code_last_count_bit = 24; - SubGhzProtocolEncoderCommon* encoder = subghz_protocol_encoder_common_alloc(); + SubGhzProtocolCommonEncoder* encoder = subghz_protocol_encoder_common_alloc(); encoder->repeat = repeat; subghz_protocol_princeton_send_key(protocol, encoder); furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); furi_hal_subghz_start_async_tx(subghz_protocol_encoder_common_yield, encoder); @@ -212,7 +212,7 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { // Configure radio furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); diff --git a/applications/subghz/subghz_history.c b/applications/subghz/subghz_history.c new file mode 100644 index 00000000..1aacdea6 --- /dev/null +++ b/applications/subghz/subghz_history.c @@ -0,0 +1,155 @@ +#include "subghz_history.h" +#include <lib/subghz/protocols/subghz_protocol_keeloq.h> +#include <lib/subghz/protocols/subghz_protocol_star_line.h> +#include <lib/subghz/protocols/subghz_protocol_princeton.h> + +#include <furi.h> +#include <m-string.h> + +#define SUBGHZ_HISTORY_MAX 20 + +typedef struct SubGhzHistoryStruct SubGhzHistoryStruct; + +struct SubGhzHistoryStruct { + const char* name; + const char* manufacture_name; + uint8_t type_protocol; + uint8_t code_count_bit; + uint64_t code_found; + uint16_t te; + FuriHalSubGhzPreset preset; + uint32_t real_frequency; +}; + +struct SubGhzHistory { + uint32_t last_update_timestamp; + uint16_t last_index_write; + uint64_t code_last_found; + SubGhzHistoryStruct history[SUBGHZ_HISTORY_MAX]; + SubGhzProtocolCommonLoad data; +}; + +SubGhzHistory* subghz_history_alloc(void) { + SubGhzHistory* instance = furi_alloc(sizeof(SubGhzHistory)); + return instance; +} + +void subghz_history_free(SubGhzHistory* instance) { + furi_assert(instance); + free(instance); +} + +void subghz_history_set_frequency_preset( + SubGhzHistory* instance, + uint16_t idx, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + furi_assert(instance); + if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return; + instance->history[idx].preset = preset; + instance->history[idx].real_frequency = frequency; +} + +uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + return instance->history[idx].real_frequency; +} + +FuriHalSubGhzPreset subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + return instance->history[idx].preset; +} + +void subghz_history_clean(SubGhzHistory* instance) { + furi_assert(instance); + instance->last_index_write = 0; + instance->code_last_found = 0; +} + +uint16_t subghz_history_get_item(SubGhzHistory* instance) { + furi_assert(instance); + return instance->last_index_write; +} + +uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + return instance->history[idx].type_protocol; +} + +const char* subghz_history_get_name(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + return instance->history[idx].name; +} + +SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + instance->data.code_found = instance->history[idx].code_found; + instance->data.code_count_bit = instance->history[idx].code_count_bit; + instance->data.param1 = instance->history[idx].te; + return &instance->data; +} + +void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx) { + if(instance->history[idx].code_count_bit < 33) { + string_printf( + output, + "%s %lX", + instance->history[idx].name, + (uint32_t)(instance->history[idx].code_found & 0xFFFFFFFF)); + } else { + string_t str_buff; + string_init(str_buff); + if(strcmp(instance->history[idx].name, "KeeLoq") == 0) { + string_set(str_buff, "KL "); + string_cat(str_buff, instance->history[idx].manufacture_name); + } else if(strcmp(instance->history[idx].name, "Star Line") == 0) { + string_set(str_buff, "SL "); + string_cat(str_buff, instance->history[idx].manufacture_name); + } else { + string_set(str_buff, instance->history[idx].name); + } + + string_printf( + output, + "%s %lX%08lX", + string_get_cstr(str_buff), + (uint32_t)(instance->history[idx].code_found >> 32), + (uint32_t)(instance->history[idx].code_found & 0xFFFFFFFF)); + string_clear(str_buff); + } +} + +void subghz_history_add_to_history(SubGhzHistory* instance, void* context) { + furi_assert(instance); + furi_assert(context); + SubGhzProtocolCommon* protocol = context; + + if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return; + if((instance->code_last_found == (protocol->code_last_found & 0xFFFF0FFFFFFFFFFF)) && + ((millis() - instance->last_update_timestamp) < 500)) { + instance->last_update_timestamp = millis(); + return; + } + + instance->code_last_found = protocol->code_last_found & 0xFFFF0FFFFFFFFFFF; + instance->last_update_timestamp = millis(); + + 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; + instance->history[instance->last_index_write].code_count_bit = protocol->code_last_count_bit; + instance->history[instance->last_index_write].code_found = protocol->code_last_found; + if(strcmp(protocol->name, "KeeLoq") == 0) { + instance->history[instance->last_index_write].manufacture_name = + subghz_protocol_keeloq_get_manufacture_name(protocol); + } else if(strcmp(protocol->name, "Star Line") == 0) { + instance->history[instance->last_index_write].manufacture_name = + subghz_protocol_star_line_get_manufacture_name(protocol); + } else if(strcmp(protocol->name, "Princeton") == 0) { + instance->history[instance->last_index_write].te = + subghz_protocol_princeton_get_te(protocol); + } + instance->history[instance->last_index_write].type_protocol = protocol->type_protocol; + + instance->last_index_write++; +}
\ No newline at end of file diff --git a/applications/subghz/subghz_history.h b/applications/subghz/subghz_history.h new file mode 100644 index 00000000..a0964fa0 --- /dev/null +++ b/applications/subghz/subghz_history.h @@ -0,0 +1,22 @@ +#pragma once + +#include <lib/subghz/protocols/subghz_protocol_common.h> + +typedef struct SubGhzHistory SubGhzHistory; + +SubGhzHistory* subghz_history_alloc(void); +void subghz_history_free(SubGhzHistory* instance); +void subghz_history_clean(SubGhzHistory* instance); +void subghz_history_set_frequency_preset( + SubGhzHistory* instance, + uint16_t idx, + uint32_t frequency, + FuriHalSubGhzPreset preset); +uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx); +FuriHalSubGhzPreset subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx); +uint16_t subghz_history_get_item(SubGhzHistory* instance); +uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx); +const char* subghz_history_get_name(SubGhzHistory* instance, uint16_t idx); +void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx); +void subghz_history_add_to_history(SubGhzHistory* instance, void* context); +SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx); diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index 03ebbc26..a339edfb 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -8,6 +8,7 @@ #include <notification/notification-messages.h> #include "file-worker.h" #include "../notification/notification.h" +#include "views/subghz_receiver.h" void subghz_begin(FuriHalSubGhzPreset preset) { furi_hal_subghz_reset(); @@ -16,30 +17,59 @@ void subghz_begin(FuriHalSubGhzPreset preset) { hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); } -void subghz_rx(uint32_t frequency) { +uint32_t subghz_rx(void* context, uint32_t frequency) { + furi_assert(context); + SubGhzWorker* worker = context; + furi_hal_subghz_idle(); - furi_hal_subghz_set_frequency_and_path(frequency); + uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); furi_hal_subghz_rx(); + + furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, worker); + subghz_worker_start(worker); + return value; } -void subghz_tx(uint32_t frequency) { +uint32_t subghz_tx(uint32_t frequency) { furi_hal_subghz_idle(); - furi_hal_subghz_set_frequency_and_path(frequency); + uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_write(&gpio_cc1101_g0, true); furi_hal_subghz_tx(); + return value; } void subghz_idle(void) { furi_hal_subghz_idle(); } -void subghz_end(void) { +void subghz_rx_end(void* context) { + furi_assert(context); + SubGhzWorker* worker = context; + + if(subghz_worker_is_running(worker)) { + subghz_worker_stop(worker); + furi_hal_subghz_stop_async_rx(); + } +} + +void subghz_sleep(void) { furi_hal_subghz_sleep(); } +void subghz_frequency_preset_to_str(void* context, string_t output) { + furi_assert(context); + SubGhz* subghz = context; + string_cat_printf( + output, + "Frequency: %d\n" + "Preset: %d\n", + (int)subghz->frequency, + (int)subghz->preset); +} + void subghz_transmitter_tx_start(void* context) { SubGhz* subghz = context; subghz->encoder = subghz_protocol_encoder_common_alloc(); @@ -47,8 +77,17 @@ void subghz_transmitter_tx_start(void* context) { //get upload if(subghz->protocol_result->get_upload_protocol) { if(subghz->protocol_result->get_upload_protocol(subghz->protocol_result, subghz->encoder)) { - subghz_begin(FuriHalSubGhzPresetOokAsync); - subghz_tx(433920000); + if(subghz->preset) { + subghz_begin(subghz->preset); + } else { + subghz_begin(FuriHalSubGhzPresetOok650Async); + } + if(subghz->frequency) { + subghz_tx(subghz->frequency); + } else { + subghz_tx(433920000); + } + //Start TX furi_hal_subghz_start_async_tx(subghz_protocol_encoder_common_yield, subghz->encoder); } @@ -59,7 +98,6 @@ void subghz_transmitter_tx_stop(void* context) { SubGhz* subghz = context; //Stop TX furi_hal_subghz_stop_async_tx(); - subghz_end(); subghz_protocol_encoder_common_free(subghz->encoder); //if protocol dynamic then we save the last upload if(subghz->protocol_result->type_protocol == TYPE_PROTOCOL_DYNAMIC) { @@ -79,12 +117,35 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { string_init_set_str(path, file_path); string_t temp_str; string_init(temp_str); + int res = 0; + int data = 0; do { if(!file_worker_open(file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { break; } - // Read and parse name protocol from 1st line + + // Read and parse frequency from 1st line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data); + if(res != 1) { + break; + } + subghz->frequency = (uint32_t)data; + + // Read and parse preset from 2st line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data); + if(res != 1) { + break; + } + subghz->preset = (FuriHalSubGhzPreset)data; + + // Read and parse name protocol from 2st line if(!file_worker_read_until(file_worker, temp_str, '\n')) { break; } @@ -93,16 +154,18 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { subghz->protocol_result = subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str)); if(subghz->protocol_result == NULL) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); break; } - if(!subghz->protocol_result->to_load_protocol(file_worker, subghz->protocol_result)) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); + if(!subghz->protocol_result->to_load_protocol_from_file( + file_worker, subghz->protocol_result)) { break; } loaded = true; } while(0); + if(!loaded) { + file_worker_show_error(file_worker, "Cannot parse\nfile"); + } string_clear(temp_str); string_clear(path); file_worker_close(file_worker); @@ -113,6 +176,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { bool subghz_save_protocol_to_file(void* context, const char* dev_name) { SubGhz* subghz = context; + furi_assert(subghz->protocol_result); FileWorker* file_worker = file_worker_alloc(false); string_t dev_file_name; string_init(dev_file_name); @@ -140,6 +204,11 @@ bool subghz_save_protocol_to_file(void* context, const char* dev_name) { file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) { break; } + //Get string frequency preset protocol + subghz_frequency_preset_to_str(subghz, temp_str); + if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) { + break; + } //Get string save subghz->protocol_result->to_save_string(subghz->protocol_result, temp_str); // Prepare and write data to file @@ -157,7 +226,7 @@ bool subghz_save_protocol_to_file(void* context, const char* dev_name) { return saved; } -bool subghz_saved_protocol_select(SubGhz* subghz) { +bool subghz_load_protocol_from_file(SubGhz* subghz) { furi_assert(subghz); FileWorker* file_worker = file_worker_alloc(false); @@ -165,6 +234,8 @@ bool subghz_saved_protocol_select(SubGhz* subghz) { string_init(protocol_file_name); string_t temp_str; string_init(temp_str); + int sscanf_res = 0; + int data = 0; // Input events and views are managed by file_select bool res = file_worker_file_select( @@ -197,7 +268,27 @@ bool subghz_saved_protocol_select(SubGhz* subghz) { file_worker, string_get_cstr(protocol_file_name), FSAM_READ, FSOM_OPEN_EXISTING)) { break; } - // Read and parse name protocol from 1st line + // Read and parse frequency from 1st line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + sscanf_res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data); + if(sscanf_res != 1) { + break; + } + subghz->frequency = (uint32_t)data; + + // Read and parse preset from 2st line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + sscanf_res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data); + if(sscanf_res != 1) { + break; + } + subghz->preset = (FuriHalSubGhzPreset)data; + + // Read and parse name protocol from 3st line if(!file_worker_read_until(file_worker, temp_str, '\n')) { break; } @@ -206,16 +297,19 @@ bool subghz_saved_protocol_select(SubGhz* subghz) { subghz->protocol_result = subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str)); if(subghz->protocol_result == NULL) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); break; } - if(!subghz->protocol_result->to_load_protocol(file_worker, subghz->protocol_result)) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); + if(!subghz->protocol_result->to_load_protocol_from_file( + file_worker, subghz->protocol_result)) { break; } res = true; } while(0); + if(!res) { + file_worker_show_error(file_worker, "Cannot parse\nfile"); + } + string_clear(temp_str); string_clear(protocol_file_name); diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index 8149363d..8b084209 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -25,12 +25,14 @@ #include <lib/subghz/subghz_worker.h> #include <lib/subghz/protocols/subghz_protocol.h> #include <lib/subghz/protocols/subghz_protocol_common.h> +#include "subghz_history.h" #define SUBGHZ_TEXT_STORE_SIZE 128 #define NOTIFICATION_STARTING_STATE 0u #define NOTIFICATION_IDLE_STATE 1u #define NOTIFICATION_TX_STATE 2u +#define NOTIFICATION_RX_STATE 3u extern const uint32_t subghz_frequencies[]; extern const uint32_t subghz_frequencies_count; @@ -43,10 +45,11 @@ struct SubGhz { SubGhzWorker* worker; SubGhzProtocol* protocol; SubGhzProtocolCommon* protocol_result; - SubGhzProtocolEncoderCommon* encoder; + SubGhzProtocolCommonEncoder* encoder; + uint32_t frequency; + FuriHalSubGhzPreset preset; SceneManager* scene_manager; - ViewDispatcher* view_dispatcher; Submenu* submenu; @@ -81,13 +84,14 @@ typedef enum { } SubGhzView; void subghz_begin(FuriHalSubGhzPreset preset); -void subghz_rx(uint32_t frequency); -void subghz_tx(uint32_t frequency); +uint32_t subghz_rx(void* context, uint32_t frequency); +uint32_t subghz_tx(uint32_t frequency); void subghz_idle(void); -void subghz_end(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); bool subghz_key_load(SubGhz* subghz, const char* file_path); bool subghz_save_protocol_to_file(void* context, const char* dev_name); -bool subghz_saved_protocol_select(SubGhz* subghz); +bool subghz_load_protocol_from_file(SubGhz* subghz); uint32_t subghz_random_serial(void); diff --git a/applications/subghz/views/subghz_analyze.c b/applications/subghz/views/subghz_analyze.c index 7380a026..cef72303 100644 --- a/applications/subghz/views/subghz_analyze.c +++ b/applications/subghz/views/subghz_analyze.c @@ -58,7 +58,7 @@ void subghz_analyze_draw(Canvas* canvas, SubghzAnalyzeModel* model) { default: canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 20, string_get_cstr(model->text)); + elements_multiline_text(canvas, 0, 18, string_get_cstr(model->text)); break; } } @@ -144,7 +144,7 @@ void subghz_analyze_enter(void* context) { furi_hal_subghz_reset(); furi_hal_subghz_idle(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); with_view_model( subghz_analyze->view, (SubghzAnalyzeModel * model) { diff --git a/applications/subghz/views/subghz_receiver.c b/applications/subghz/views/subghz_receiver.c index a4d9aef7..147811dc 100644 --- a/applications/subghz/views/subghz_receiver.c +++ b/applications/subghz/views/subghz_receiver.c @@ -1,25 +1,55 @@ #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> +#define FRAME_HEIGHT 12 +#define MAX_LEN_PX 100 +#define MENU_ITEMS 4 + +typedef enum { + ReceiverSceneStart, + ReceiverSceneMain, + ReceiverSceneConfig, + ReceiverSceneInfo, +} SubghzReceiverScene; + +static const Icon* ReceiverItemIcons[] = { + [TYPE_PROTOCOL_UNKNOWN] = &I_quest_7x8, + [TYPE_PROTOCOL_STATIC] = &I_unlock_7x8, + [TYPE_PROTOCOL_DYNAMIC] = &I_lock_7x8, +}; + struct SubghzReceiver { View* view; SubghzReceiverCallback callback; void* context; + SubGhzWorker* worker; + SubGhzProtocol* protocol; }; typedef struct { string_t text; uint16_t scene; - SubGhzProtocolCommon* protocol; + SubGhzProtocolCommon* protocol_result; + SubGhzHistory* history; + uint8_t frequency; + uint8_t temp_frequency; + uint32_t real_frequency; + + uint8_t tab_idx; + uint8_t menu_idx; + uint16_t idx; + uint16_t list_offset; + uint16_t history_item; + bool menu; } SubghzReceiverModel; void subghz_receiver_set_callback( @@ -32,50 +62,323 @@ void subghz_receiver_set_callback( subghz_receiver->context = context; } -void subghz_receiver_set_protocol(SubghzReceiver* subghz_receiver, SubGhzProtocolCommon* protocol) { +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 = protocol; + 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); + + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + size_t history_item = model->history_item; + uint16_t bounds = history_item > 3 ? 2 : history_item; + + if(history_item > 3 && model->idx >= history_item - 1) { + model->list_offset = model->idx - 3; + } else if(model->list_offset < model->idx - bounds) { + model->list_offset = CLAMP(model->list_offset + 1, history_item - bounds, 0); + } else if(model->list_offset > model->idx - bounds) { + model->list_offset = CLAMP(model->idx - 1, history_item - bounds, 0); + } + 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); + + canvas_set_color(canvas, ColorWhite); + canvas_draw_dot(canvas, 0, 0 + idx * FRAME_HEIGHT); + canvas_draw_dot(canvas, 1, 0 + idx * FRAME_HEIGHT); + canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 1); + + canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 11); + canvas_draw_dot(canvas, scrollbar ? 121 : 126, 0 + idx * FRAME_HEIGHT); + canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11); } void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) { + bool scrollbar = model->history_item > 4; + string_t str_buff; + char buffer[64]; + string_init(str_buff); + canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 10, string_get_cstr(model->text)); - elements_button_left(canvas, "Back"); - if(model->protocol && model->protocol->to_save_string && - strcmp(model->protocol->name, "KeeLoq")) { - elements_button_right(canvas, "Save"); + 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, 126, 0, 49, model->idx, model->history_item); + } + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontPrimary); + snprintf( + buffer, + sizeof(buffer), + "%03ld.%03ld OOK", + model->real_frequency / 1000000 % 1000, + model->real_frequency / 1000 % 1000); + canvas_draw_str(canvas, 60, 61, buffer); + elements_button_left(canvas, "Config"); + break; + + case ReceiverSceneStart: + canvas_draw_icon(canvas, 0, 0, &I_RFIDDolphinReceive_97x61); + canvas_invert_color(canvas); + canvas_draw_box(canvas, 80, 2, 20, 20); + canvas_invert_color(canvas); + canvas_draw_icon(canvas, 75, 8, &I_sub1_10px); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 63, 40, "Scanning..."); + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontPrimary); + snprintf( + buffer, + sizeof(buffer), + "%03ld.%03ld OOK", + model->real_frequency / 1000000 % 1000, + model->real_frequency / 1000 % 1000); + canvas_draw_str(canvas, 60, 61, buffer); + elements_button_left(canvas, "Config"); + break; + + case ReceiverSceneConfig: + snprintf( + buffer, + sizeof(buffer), + "Frequency: < %03ld.%03ldMHz >", + model->real_frequency / 1000000 % 1000, + model->real_frequency / 1000 % 1000); + canvas_draw_str(canvas, 0, 8, buffer); + elements_button_center(canvas, "Save"); + break; + + case ReceiverSceneInfo: + canvas_set_font(canvas, FontSecondary); + elements_multiline_text(canvas, 0, 8, string_get_cstr(model->text)); + snprintf( + buffer, + sizeof(buffer), + "%03ld.%03ld", + subghz_history_get_frequency(model->history, model->idx) / 1000000 % 1000, + subghz_history_get_frequency(model->history, model->idx) / 1000 % 1000); + canvas_draw_str(canvas, 90, 8, buffer); + if(model->protocol_result && model->protocol_result->to_save_string && + strcmp(model->protocol_result->name, "KeeLoq")) { + elements_button_right(canvas, "Save"); + elements_button_center(canvas, "Send"); + } + break; + + default: + + break; } + + string_clear(str_buff); } bool subghz_receiver_input(InputEvent* event, void* context) { furi_assert(context); - SubghzReceiver* subghz_receiver = context; - if(event->type != InputTypeShort) return false; - - bool can_be_saved = false; + uint8_t scene = 0; + SubghzReceiver* subghz_receiver = context; with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - can_be_saved = - (model->protocol && model->protocol->to_save_string && - strcmp(model->protocol->name, "KeeLoq")); + scene = model->scene; return false; }); - if(event->key == InputKeyBack) { - return false; - } else if(event->key == InputKeyLeft) { - subghz_receiver->callback(SubghzReceverEventBack, subghz_receiver->context); - } else if(can_be_saved && event->key == InputKeyRight) { - subghz_receiver->callback(SubghzReceverEventSave, subghz_receiver->context); + if(scene != ReceiverSceneInfo && event->type != InputTypeShort) return false; + + bool can_be_saved = false; + + switch(scene) { + case ReceiverSceneMain: + if(event->key == InputKeyBack) { + return false; + } else if(event->key == InputKeyUp) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + if(model->idx != 0) model->idx--; + return true; + }); + } else if(event->key == InputKeyDown) { + 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) { + 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) { + 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: + 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(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]); + 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_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->callback(SubghzReceverEventSendStop, subghz_receiver->context); + return true; + } + break; + + case ReceiverSceneConfig: + if(event->key == InputKeyBack) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + model->frequency = model->temp_frequency; + model->real_frequency = subghz_frequencies[model->frequency]; + 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) { + subghz_rx_end(subghz_receiver->worker); + 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_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 - 1) model->frequency++; + model_updated = true; + } + if(model_updated) { + model->real_frequency = subghz_frequencies[model->frequency]; + } + return model_updated; + }); + } + break; + + case ReceiverSceneStart: + if(event->key == InputKeyBack) { + return false; + } else if(event->key == InputKeyLeft) { + 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); return true; } @@ -86,19 +389,53 @@ void subghz_receiver_text_callback(string_t text, void* context) { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { string_set(model->text, text); - model->scene = 0; + 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; + return true; + }); + subghz_protocol_reset(subghz_receiver->protocol); + subghz_receiver_update_offset(subghz_receiver); +} + 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) { - model->protocol->to_string(model->protocol, model->text); + subghz_rx_end(subghz_receiver->worker); + model->frequency = subghz_frequencies_433_92; + model->real_frequency = + subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]); + if(subghz_history_get_item(model->history) == 0) { + model->scene = ReceiverSceneStart; + } else { + model->scene = ReceiverSceneMain; + } return true; }); + subghz_protocol_enable_dump( + subghz_receiver->protocol, subghz_receiver_protocol_callback, subghz_receiver); } void subghz_receiver_exit(void* context) { @@ -109,6 +446,9 @@ void subghz_receiver_exit(void* context) { string_clean(model->text); return true; }); + // Stop CC1101 Rx + subghz_rx_end(subghz_receiver->worker); + subghz_sleep(); } SubghzReceiver* subghz_receiver_alloc() { @@ -126,6 +466,7 @@ SubghzReceiver* subghz_receiver_alloc() { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { string_init(model->text); + model->history = subghz_history_alloc(); return true; }); return subghz_receiver; @@ -137,7 +478,8 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver) { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { string_clear(model->text); - return true; + subghz_history_free(model->history); + return false; }); view_free(subghz_receiver->view); free(subghz_receiver); @@ -147,3 +489,44 @@ View* subghz_receiver_get_view(SubghzReceiver* subghz_receiver) { furi_assert(subghz_receiver); return subghz_receiver->view; } + +uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver) { + furi_assert(subghz_receiver); + uint32_t frequency; + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + frequency = subghz_history_get_frequency(model->history, model->idx); + return false; + }); + return frequency; +} + +FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver) { + 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; + }); + 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); +}
\ No newline at end of file diff --git a/applications/subghz/views/subghz_receiver.h b/applications/subghz/views/subghz_receiver.h index 924f90b8..b4aa7bbc 100644 --- a/applications/subghz/views/subghz_receiver.h +++ b/applications/subghz/views/subghz_receiver.h @@ -2,10 +2,19 @@ #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 } SubghzReceverEvent; typedef struct SubghzReceiver SubghzReceiver; @@ -23,4 +32,12 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver); View* subghz_receiver_get_view(SubghzReceiver* subghz_receiver); -void subghz_receiver_set_protocol(SubghzReceiver* subghz_receiver, SubGhzProtocolCommon* protocol); +void subghz_receiver_set_protocol( + SubghzReceiver* subghz_receiver, + SubGhzProtocolCommon* protocol_result, + SubGhzProtocol* protocol); +SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver); +void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker); +uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver); +FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver); +void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output); diff --git a/applications/subghz/views/subghz_static.c b/applications/subghz/views/subghz_static.c index 25c9b9b4..bdb11753 100644 --- a/applications/subghz/views/subghz_static.c +++ b/applications/subghz/views/subghz_static.c @@ -112,7 +112,7 @@ void subghz_static_enter(void* context) { SubghzStatic* instance = context; furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_write(&gpio_cc1101_g0, false); diff --git a/applications/subghz/views/subghz_test_carrier.c b/applications/subghz/views/subghz_test_carrier.c index acd1dacb..82d11650 100644 --- a/applications/subghz/views/subghz_test_carrier.c +++ b/applications/subghz/views/subghz_test_carrier.c @@ -119,7 +119,7 @@ void subghz_test_carrier_enter(void* context) { SubghzTestCarrier* subghz_test_carrier = context; furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); diff --git a/applications/subghz/views/subghz_test_packet.c b/applications/subghz/views/subghz_test_packet.c index 66a8eeee..f1c48179 100644 --- a/applications/subghz/views/subghz_test_packet.c +++ b/applications/subghz/views/subghz_test_packet.c @@ -166,7 +166,7 @@ void subghz_test_packet_enter(void* context) { SubghzTestPacket* instance = context; furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); with_view_model( instance->view, (SubghzTestPacketModel * model) { diff --git a/applications/subghz/views/subghz_transmitter.c b/applications/subghz/views/subghz_transmitter.c index 1ba76d97..efa35fde 100644 --- a/applications/subghz/views/subghz_transmitter.c +++ b/applications/subghz/views/subghz_transmitter.c @@ -8,7 +8,8 @@ #include <gui/elements.h> #include <notification/notification-messages.h> -#include <assets_icons.h> +//#include <assets_icons.h> +#include <gui/icon_i.h> struct SubghzTransmitter { View* view; @@ -19,6 +20,8 @@ struct SubghzTransmitter { typedef struct { string_t text; uint16_t scene; + uint32_t real_frequency; + FuriHalSubGhzPreset preset; SubGhzProtocolCommon* protocol; } SubghzTransmitterModel; @@ -42,14 +45,65 @@ void subghz_transmitter_set_protocol( }); } +void subghz_transmitter_set_frequency_preset( + SubghzTransmitter* subghz_transmitter, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + with_view_model( + subghz_transmitter->view, (SubghzTransmitterModel * model) { + model->real_frequency = frequency; + model->preset = preset; + return true; + }); +} + +static void subghz_transmitter_button_right(Canvas* canvas, const char* str) { + const uint8_t button_height = 13; + const uint8_t vertical_offset = 3; + const uint8_t horizontal_offset = 1; + const uint8_t string_width = canvas_string_width(canvas, str); + const Icon* icon = &I_ButtonCenter_7x7; + const uint8_t icon_offset = 3; + const uint8_t icon_width_with_offset = icon->width + icon_offset; + const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; + + const uint8_t x = (canvas_width(canvas) - button_width) / 2 + 40; + const uint8_t y = canvas_height(canvas); + + canvas_draw_box(canvas, x, y - button_height, button_width, button_height); + + canvas_draw_line(canvas, x - 1, y, x - 1, y - button_height + 0); + canvas_draw_line(canvas, x - 2, y, x - 2, y - button_height + 1); + canvas_draw_line(canvas, x - 3, y, x - 3, y - button_height + 2); + + canvas_draw_line(canvas, x + button_width + 0, y, x + button_width + 0, y - button_height + 0); + canvas_draw_line(canvas, x + button_width + 1, y, x + button_width + 1, y - button_height + 1); + canvas_draw_line(canvas, x + button_width + 2, y, x + button_width + 2, y - button_height + 2); + + canvas_invert_color(canvas); + canvas_draw_icon( + canvas, x + horizontal_offset, y - button_height + vertical_offset, &I_ButtonCenter_7x7); + canvas_draw_str( + canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str); + canvas_invert_color(canvas); +} + 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, 10, string_get_cstr(model->text)); + 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) { - elements_button_center(canvas, "Send"); + subghz_transmitter_button_right(canvas, "Send"); } } diff --git a/applications/subghz/views/subghz_transmitter.h b/applications/subghz/views/subghz_transmitter.h index 2c1f1b72..6f289e4d 100644 --- a/applications/subghz/views/subghz_transmitter.h +++ b/applications/subghz/views/subghz_transmitter.h @@ -27,3 +27,7 @@ View* subghz_transmitter_get_view(SubghzTransmitter* subghz_transmitter); void subghz_transmitter_set_protocol( SubghzTransmitter* subghz_transmitter, SubGhzProtocolCommon* protocol); +void subghz_transmitter_set_frequency_preset( + SubghzTransmitter* subghz_transmitter, + uint32_t frequency, + FuriHalSubGhzPreset preset); |