[FL-2047] SubGhz: New GUI ReadRAW view (#832)

* SubGhz: GUI RAW Read view
* SubGhz:  GUI Read RAW refactoring
* SubGhz: fix bug wrong frequency of the allowed transmission
* GUI Read RAW refactoring
* SubGhz: fix set the default frequency
* SubGhz: fix save filename when returning from another menu
* SubGhz: fix Send and Back button behavior

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
Skorpionm 2021-11-24 17:59:45 +04:00 committed by GitHub
parent 01f08f99b1
commit a13f87fedb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 407 additions and 151 deletions

View file

@ -14,8 +14,8 @@ typedef enum {
SubghzCustomEventSceneShowError,
SubghzCustomEventSceneShowOnlyRX,
SubghzCustomEventSceneNeedSavingNo,
SubghzCustomEventSceneNeedSavingYes,
SubghzCustomEventSceneExit,
SubghzCustomEventSceneStay,
SubghzCustomEventViewReceverOK,
SubghzCustomEventViewReceverConfig,
@ -25,7 +25,10 @@ typedef enum {
SubghzCustomEventViewReadRAWIDLE,
SubghzCustomEventViewReadRAWREC,
SubghzCustomEventViewReadRAWConfig,
SubghzCustomEventViewReadRAWMore,
SubghzCustomEventViewReadRAWErase,
SubghzCustomEventViewReadRAWSendStart,
SubghzCustomEventViewReadRAWSendStop,
SubghzCustomEventViewReadRAWSave,
SubghzCustomEventViewTransmitterBack,
SubghzCustomEventViewTransmitterSendStart,

View file

@ -18,5 +18,4 @@ ADD_SCENE(subghz, test_packet, TestPacket)
ADD_SCENE(subghz, set_type, SetType)
ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer)
ADD_SCENE(subghz, read_raw, ReadRAW)
ADD_SCENE(subghz, read_raw_menu, ReadRAWMenu)
ADD_SCENE(subghz, need_saving, NeedSaving)

View file

@ -6,42 +6,46 @@ void subghz_scene_need_saving_callback(GuiButtonType result, InputType type, voi
SubGhz* subghz = context;
if((result == GuiButtonTypeRight) && (type == InputTypeShort)) {
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubghzCustomEventSceneNeedSavingYes);
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubghzCustomEventSceneStay);
} else if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) {
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubghzCustomEventSceneNeedSavingNo);
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubghzCustomEventSceneExit);
}
}
void subghz_scene_need_saving_on_enter(void* context) {
SubGhz* subghz = context;
widget_add_string_multiline_element(
subghz->widget, 64, 13, AlignCenter, AlignCenter, FontPrimary, "Exit to Gub-Ghz menu?");
widget_add_string_multiline_element(
subghz->widget,
64,
25,
32,
AlignCenter,
AlignCenter,
FontSecondary,
"There is an unsaved data.\nDo you want to save it?");
"All unsaved will be\nlost.");
widget_add_button_element(
subghz->widget, GuiButtonTypeRight, "Save", subghz_scene_need_saving_callback, subghz);
subghz->widget, GuiButtonTypeRight, "Stay", subghz_scene_need_saving_callback, subghz);
widget_add_button_element(
subghz->widget, GuiButtonTypeLeft, "Delete", subghz_scene_need_saving_callback, subghz);
subghz->widget, GuiButtonTypeLeft, "Exit", subghz_scene_need_saving_callback, subghz);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewWidget);
}
bool subghz_scene_need_saving_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubghzCustomEventSceneNeedSavingYes) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateNeedSave;
if(event.type == SceneManagerEventTypeBack) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateBack;
scene_manager_previous_scene(subghz->scene_manager);
return true;
} else if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubghzCustomEventSceneStay) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateBack;
scene_manager_previous_scene(subghz->scene_manager);
return true;
} else if(event.event == SubghzCustomEventSceneNeedSavingNo) {
} else if(event.event == SubghzCustomEventSceneExit) {
if(subghz->txrx->rx_key_state == SubGhzRxKeyStateExit) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
scene_manager_search_and_switch_to_previous_scene(

View file

@ -2,6 +2,9 @@
#include "../views/subghz_read_raw.h"
#include <lib/subghz/protocols/subghz_protocol_raw.h>
#include <lib/subghz/subghz_parser.h>
#include <lib/toolbox/path.h>
#define RAW_FILE_NAME "Raw_temp"
static void subghz_scene_read_raw_update_statusbar(void* context) {
furi_assert(context);
@ -27,13 +30,20 @@ void subghz_scene_read_raw_callback(SubghzCustomEvent event, void* context) {
view_dispatcher_send_custom_event(subghz->view_dispatcher, event);
}
void subghz_scene_read_raw_callback_end_tx(void* context) {
furi_assert(context);
SubGhz* subghz = context;
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubghzCustomEventViewReadRAWSendStop);
}
void subghz_scene_read_raw_on_enter(void* context) {
SubGhz* subghz = context;
if(subghz->txrx->rx_key_state == SubGhzRxKeyStateNeedSave) {
view_dispatcher_send_custom_event(
subghz->view_dispatcher, SubghzCustomEventViewReadRAWMore);
if(subghz->txrx->rx_key_state == SubGhzRxKeyStateBack) {
subghz_read_raw_set_status(subghz->subghz_read_raw, SubghzReadRAWStatusIDLE);
} else {
subghz_read_raw_set_status(subghz->subghz_read_raw, SubghzReadRAWStatusStart);
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
}
@ -46,6 +56,11 @@ void subghz_scene_read_raw_on_enter(void* context) {
subghz_worker_set_pair_callback(
subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_parser_raw_parse);
subghz_protocol_raw_file_encoder_worker_set_callback_end(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result,
subghz_scene_read_raw_callback_end_tx,
subghz);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewReadRAW);
}
@ -54,20 +69,29 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
switch(event.event) {
case SubghzCustomEventViewReadRAWBack:
//Stop TX
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
subghz_tx_stop(subghz);
subghz_sleep(subghz);
}
//Stop RX
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
subghz_rx_end(subghz);
subghz_sleep(subghz);
};
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
//Stop save file
subghz_protocol_raw_save_to_file_stop(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result);
subghz->state_notifications = SubGhzNotificationStateIDLE;
if(subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) {
//needed save?
if((subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) ||
(subghz->txrx->rx_key_state == SubGhzRxKeyStateBack)) {
subghz->txrx->rx_key_state = SubGhzRxKeyStateExit;
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving);
} else {
//Restore default setting
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart);
}
@ -80,6 +104,63 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
return true;
break;
case SubghzCustomEventViewReadRAWErase:
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
return true;
break;
case SubghzCustomEventViewReadRAWSendStart:
//set the path to read the file
if(strcmp(
subghz_protocol_raw_get_last_file_name(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result),
"")) {
string_t temp_str;
string_init_printf(
temp_str,
"%s",
subghz_protocol_raw_get_last_file_name(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result));
path_extract_filename_no_ext(string_get_cstr(temp_str), temp_str);
strlcpy(
subghz->file_name,
string_get_cstr(temp_str),
strlen(string_get_cstr(temp_str)) + 1);
string_printf(
temp_str,
"%s/%s%s",
SUBGHZ_APP_PATH_FOLDER,
subghz->file_name,
SUBGHZ_APP_EXTENSION);
subghz_protocol_raw_set_last_file_name(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result, string_get_cstr(temp_str));
string_clear(temp_str);
//start send
subghz->state_notifications = SubGhzNotificationStateIDLE;
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
subghz_rx_end(subghz);
}
if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) ||
(subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
if(!subghz_tx_start(subghz)) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx);
} else {
subghz->state_notifications = SubGhzNotificationStateTX;
subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey;
}
}
}
return true;
break;
case SubghzCustomEventViewReadRAWSendStop:
subghz->state_notifications = SubGhzNotificationStateIDLE;
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
subghz_tx_stop(subghz);
subghz_sleep(subghz);
}
subghz_read_raw_stop_send(subghz->subghz_read_raw);
return true;
break;
case SubghzCustomEventViewReadRAWIDLE:
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
subghz_rx_end(subghz);
@ -101,7 +182,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
subghz_get_preset_name(subghz, subghz->error_str);
if(subghz_protocol_raw_save_to_file_init(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result,
"Raw_temp",
RAW_FILE_NAME,
subghz->txrx->frequency,
string_get_cstr(subghz->error_str))) {
if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) ||
@ -118,21 +199,25 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
return true;
break;
case SubghzCustomEventViewReadRAWMore:
case SubghzCustomEventViewReadRAWSave:
if(strcmp(
subghz_protocol_raw_get_last_file_name(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result),
"")) {
strlcpy(
subghz->file_name,
subghz_protocol_raw_get_last_file_name(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result),
strlen(subghz_protocol_raw_get_last_file_name(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result)) +
1);
//set the path to read the file
string_t temp_str;
string_init_printf(
temp_str,
"%s",
subghz_protocol_raw_get_last_file_name(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result));
path_extract_filename_no_ext(string_get_cstr(temp_str), temp_str);
strlcpy(
subghz->file_name,
string_get_cstr(temp_str),
strlen(string_get_cstr(temp_str)) + 1);
//set the path to read the file
string_printf(
temp_str,
"%s/%s%s",
SUBGHZ_APP_PATH_FOLDER,
@ -142,7 +227,10 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
(SubGhzProtocolRAW*)subghz->txrx->protocol_result, string_get_cstr(temp_str));
string_clear(temp_str);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAWMenu);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAW, SubghzCustomEventManagerSet);
subghz->txrx->rx_key_state = SubGhzRxKeyStateBack;
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
}
return true;
break;
@ -160,6 +248,10 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
(SubGhzProtocolRAW*)subghz->txrx->protocol_result));
subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, furi_hal_subghz_get_rssi());
break;
case SubGhzNotificationStateTX:
notification_message(subghz->notifications, &sequence_blink_green_10);
subghz_read_raw_update_sin(subghz->subghz_read_raw);
break;
default:
break;
}

View file

@ -1,72 +0,0 @@
#include "../subghz_i.h"
enum SubmenuIndex {
SubmenuIndexEmulate,
SubmenuIndexEdit,
SubmenuIndexDelete,
};
void subghz_scene_read_raw_menu_submenu_callback(void* context, uint32_t index) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, index);
}
void subghz_scene_read_raw_menu_on_enter(void* context) {
SubGhz* subghz = context;
submenu_add_item(
subghz->submenu,
"Emulate",
SubmenuIndexEmulate,
subghz_scene_read_raw_menu_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Save",
SubmenuIndexEdit,
subghz_scene_read_raw_menu_submenu_callback,
subghz);
submenu_add_item(
subghz->submenu,
"Delete",
SubmenuIndexDelete,
subghz_scene_read_raw_menu_submenu_callback,
subghz);
submenu_set_selected_item(
subghz->submenu,
scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSavedMenu));
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewMenu);
}
bool subghz_scene_read_raw_menu_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexEmulate) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAWMenu, SubmenuIndexEmulate);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTransmitter);
return true;
} else if(event.event == SubmenuIndexDelete) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAWMenu, SubmenuIndexDelete);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDelete);
return true;
} else if(event.event == SubmenuIndexEdit) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAWMenu, SubghzCustomEventManagerSet);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
return true;
}
}
return false;
}
void subghz_scene_read_raw_menu_on_exit(void* context) {
SubGhz* subghz = context;
submenu_clean(subghz->submenu);
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
}

View file

@ -2,6 +2,7 @@
#include <lib/toolbox/random_name.h>
#include "file-worker.h"
#include "../helpers/subghz_custom_event.h"
#include <lib/subghz/protocols/subghz_protocol_raw.h>
void subghz_scene_save_name_text_input_callback(void* context) {
SubGhz* subghz = context;
@ -20,7 +21,7 @@ void subghz_scene_save_name_on_enter(void* context) {
dev_name_empty = true;
} else {
memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name) + 1);
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAWMenu) ==
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
SubghzCustomEventManagerSet) {
subghz_get_next_name_file(subghz);
}
@ -49,6 +50,11 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
subghz_save_protocol_to_file(subghz, subghz->file_name);
}
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
SubghzCustomEventManagerSet) {
subghz_protocol_raw_set_last_file_name(
(SubGhzProtocolRAW*)subghz->txrx->protocol_result, subghz->file_name);
}
subghz_file_name_clear(subghz);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess);
return true;
@ -68,5 +74,5 @@ void subghz_scene_save_name_on_exit(void* context) {
// Clear view
text_input_clean(subghz->text_input);
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneReadRAWMenu, SubghzCustomEventManagerNoSet);
subghz->scene_manager, SubGhzSceneReadRAW, SubghzCustomEventManagerNoSet);
}

View file

@ -26,8 +26,11 @@ bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent event)
if(event.event == SubghzCustomEventSceneSaveSuccess) {
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneReceiver)) {
scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart);
if(!scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneReadRAW)) {
scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart);
}
}
return true;
}

View file

@ -23,7 +23,7 @@ void subghz_scene_start_on_enter(void* context) {
subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz);
submenu_add_item(
subghz->submenu,
"Read Raw",
"Read RAW",
SubmenuIndexReadRAW,
subghz_scene_start_submenu_callback,
subghz);
@ -57,6 +57,7 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.event == SubmenuIndexReadRAW) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexReadRAW);
subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE;
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW);
return true;
} else if(event.event == SubmenuIndexRead) {

View file

@ -70,6 +70,7 @@ typedef enum {
SubGhzRxKeyStateIDLE,
SubGhzRxKeyStateNoSave,
SubGhzRxKeyStateNeedSave,
SubGhzRxKeyStateBack,
SubGhzRxKeyStateAddKey,
SubGhzRxKeyStateExit,
} SubGhzRxKeyState;

View file

@ -11,13 +11,6 @@
#include <assets_icons.h>
#define SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE 100
typedef enum {
SubghzReadRAWStatusStart,
SubghzReadRAWStatusIDLE,
SubghzReadRAWStatusREC,
//SubghzReadRAWStatusShowName,
} SubghzReadRAWStatus;
struct SubghzReadRAW {
View* view;
SubghzReadRAWCallback callback;
@ -31,6 +24,7 @@ typedef struct {
uint8_t* rssi_history;
bool rssi_history_end;
uint8_t ind_write;
uint8_t ind_sin;
SubghzReadRAWStatus satus;
} SubghzReadRAWModel;
@ -89,6 +83,88 @@ void subghz_read_raw_update_sample_write(SubghzReadRAW* instance, size_t sample)
});
}
void subghz_read_raw_stop_send(SubghzReadRAW* instance) {
furi_assert(instance);
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
if(model->satus == SubghzReadRAWStatusTXRepeat) {
// Start TX
instance->callback(SubghzCustomEventViewReadRAWSendStart, instance->context);
} else {
model->satus = SubghzReadRAWStatusIDLE;
}
return true;
});
}
void subghz_read_raw_update_sin(SubghzReadRAW* instance) {
furi_assert(instance);
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
if(model->ind_sin++ > 62) {
model->ind_sin = 0;
}
return true;
});
}
static int8_t subghz_read_raw_tab_sin(uint8_t x) {
const uint8_t tab_sin[64] = {0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37,
40, 43, 46, 49, 51, 54, 57, 60, 63, 65, 68, 71, 73,
76, 78, 81, 83, 85, 88, 90, 92, 94, 96, 98, 100, 102,
104, 106, 107, 109, 111, 112, 113, 115, 116, 117, 118, 120, 121,
122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127};
int8_t r = tab_sin[((x & 0x40) ? -x - 1 : x) & 0x3f];
if(x & 0x80) return -r;
return r;
}
void subghz_read_raw_draw_sin(Canvas* canvas, SubghzReadRAWModel* model) {
#define SUBGHZ_RAW_SIN_AMPLITUDE 11
for(int i = 114; i > 0; i--) {
canvas_draw_line(
canvas,
i,
32 - subghz_read_raw_tab_sin(i + model->ind_sin * 16) / SUBGHZ_RAW_SIN_AMPLITUDE,
i + 1,
32 + subghz_read_raw_tab_sin((i + model->ind_sin * 16 + 1) * 2) /
SUBGHZ_RAW_SIN_AMPLITUDE);
canvas_draw_line(
canvas,
i + 1,
32 - subghz_read_raw_tab_sin((i + model->ind_sin * 16)) / SUBGHZ_RAW_SIN_AMPLITUDE,
i + 2,
32 + subghz_read_raw_tab_sin((i + model->ind_sin * 16 + 1) * 2) /
SUBGHZ_RAW_SIN_AMPLITUDE);
}
}
void subghz_read_raw_draw_scale(Canvas* canvas, SubghzReadRAWModel* model) {
#define SUBGHZ_RAW_TOP_SCALE 14
#define SUBGHZ_RAW_END_SCALE 115
if(model->rssi_history_end == false) {
for(int i = SUBGHZ_RAW_END_SCALE; i > 0; i -= 15) {
canvas_draw_line(canvas, i, SUBGHZ_RAW_TOP_SCALE, i, SUBGHZ_RAW_TOP_SCALE + 4);
canvas_draw_line(canvas, i - 5, SUBGHZ_RAW_TOP_SCALE, i - 5, SUBGHZ_RAW_TOP_SCALE + 2);
canvas_draw_line(
canvas, i - 10, SUBGHZ_RAW_TOP_SCALE, i - 10, SUBGHZ_RAW_TOP_SCALE + 2);
}
} else {
for(int i = SUBGHZ_RAW_END_SCALE - model->ind_write % 15; i > -15; i -= 15) {
canvas_draw_line(canvas, i, SUBGHZ_RAW_TOP_SCALE, i, SUBGHZ_RAW_TOP_SCALE + 4);
if(SUBGHZ_RAW_END_SCALE > i + 5)
canvas_draw_line(
canvas, i + 5, SUBGHZ_RAW_TOP_SCALE, i + 5, SUBGHZ_RAW_TOP_SCALE + 2);
if(SUBGHZ_RAW_END_SCALE > i + 10)
canvas_draw_line(
canvas, i + 10, SUBGHZ_RAW_TOP_SCALE, i + 10, SUBGHZ_RAW_TOP_SCALE + 2);
}
}
}
void subghz_read_raw_draw_rssi(Canvas* canvas, SubghzReadRAWModel* model) {
int ind = 0;
int base = 0;
@ -134,17 +210,26 @@ void subghz_read_raw_draw(Canvas* canvas, SubghzReadRAWModel* model) {
canvas, 126, 0, AlignRight, AlignTop, string_get_cstr(model->sample_write));
canvas_draw_line(canvas, 0, 14, 115, 14);
subghz_read_raw_draw_rssi(canvas, model);
canvas_draw_line(canvas, 0, 48, 115, 48);
canvas_draw_line(canvas, 115, 14, 115, 48);
subghz_read_raw_draw_scale(canvas, model);
if((model->satus == SubghzReadRAWStatusTX) || (model->satus == SubghzReadRAWStatusTXRepeat)) {
subghz_read_raw_draw_sin(canvas, model);
} else {
subghz_read_raw_draw_rssi(canvas, model);
}
if(model->satus == SubghzReadRAWStatusIDLE) {
elements_button_left(canvas, "Config");
elements_button_center(canvas, "REC");
elements_button_right(canvas, "More");
elements_button_left(canvas, "Erase");
elements_button_center(canvas, "Send");
elements_button_right(canvas, "Save");
} else if(model->satus == SubghzReadRAWStatusStart) {
elements_button_left(canvas, "Config");
elements_button_center(canvas, "REC");
} else if(
(model->satus == SubghzReadRAWStatusTX) || (model->satus == SubghzReadRAWStatusTXRepeat)) {
elements_button_center(canvas, "Send");
} else {
elements_button_center(canvas, "Stop");
}
@ -158,35 +243,83 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
furi_assert(context);
SubghzReadRAW* instance = context;
if(event->key == InputKeyBack && event->type == InputTypeShort) {
instance->callback(SubghzCustomEventViewReadRAWBack, instance->context);
if(event->key == InputKeyOk && event->type == InputTypePress) {
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
uint8_t ret = false;
if(model->satus == SubghzReadRAWStatusIDLE) {
// Start TX
instance->callback(SubghzCustomEventViewReadRAWSendStart, instance->context);
model->satus = SubghzReadRAWStatusTXRepeat;
ret = true;
} else if(model->satus == SubghzReadRAWStatusTX) {
model->satus = SubghzReadRAWStatusTXRepeat;
}
return ret;
});
} else if(event->key == InputKeyOk && event->type == InputTypeRelease) {
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
if(model->satus == SubghzReadRAWStatusTXRepeat) {
// Stop repeat TX
model->satus = SubghzReadRAWStatusTX;
}
return false;
});
} else if(event->key == InputKeyBack && event->type == InputTypeShort) {
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
if(model->satus == SubghzReadRAWStatusREC) {
//Stop REC
instance->callback(SubghzCustomEventViewReadRAWIDLE, instance->context);
model->satus = SubghzReadRAWStatusIDLE;
} else {
//Exit
instance->callback(SubghzCustomEventViewReadRAWBack, instance->context);
}
return true;
});
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
if(model->satus == SubghzReadRAWStatusIDLE ||
model->satus == SubghzReadRAWStatusStart) {
if(model->satus == SubghzReadRAWStatusStart) {
//Config
instance->callback(SubghzCustomEventViewReadRAWConfig, instance->context);
}
if(model->satus == SubghzReadRAWStatusIDLE) {
//Erase
model->satus = SubghzReadRAWStatusStart;
model->rssi_history_end = false;
model->ind_write = 0;
string_set(model->sample_write, "0 spl.");
instance->callback(SubghzCustomEventViewReadRAWErase, instance->context);
}
return true;
});
} else if(event->key == InputKeyRight && event->type == InputTypeShort) {
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
//Save
if(model->satus == SubghzReadRAWStatusIDLE) {
instance->callback(SubghzCustomEventViewReadRAWMore, instance->context);
instance->callback(SubghzCustomEventViewReadRAWSave, instance->context);
}
return true;
});
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
if(model->satus == SubghzReadRAWStatusIDLE ||
model->satus == SubghzReadRAWStatusStart) {
if(model->satus == SubghzReadRAWStatusStart) {
//Record
instance->callback(SubghzCustomEventViewReadRAWREC, instance->context);
model->satus = SubghzReadRAWStatusREC;
model->ind_write = 0;
model->rssi_history_end = false;
} else {
} else if(
(model->satus != SubghzReadRAWStatusTX) &&
(model->satus != SubghzReadRAWStatusTXRepeat)) {
//Stop
instance->callback(SubghzCustomEventViewReadRAWIDLE, instance->context);
model->satus = SubghzReadRAWStatusIDLE;
}
@ -197,19 +330,29 @@ bool subghz_read_raw_input(InputEvent* event, void* context) {
return true;
}
void subghz_read_raw_set_status(SubghzReadRAW* instance, SubghzReadRAWStatus satus) {
furi_assert(instance);
if(satus == SubghzReadRAWStatusStart) {
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
model->satus = SubghzReadRAWStatusStart;
model->rssi_history_end = false;
model->ind_write = 0;
string_set(model->sample_write, "0 spl.");
return true;
});
} else if(satus == SubghzReadRAWStatusIDLE) {
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
model->satus = SubghzReadRAWStatusIDLE;
return true;
});
}
}
void subghz_read_raw_enter(void* context) {
furi_assert(context);
SubghzReadRAW* instance = context;
with_view_model(
instance->view, (SubghzReadRAWModel * model) {
model->satus = SubghzReadRAWStatusStart;
model->rssi_history = furi_alloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t));
model->rssi_history_end = false;
model->ind_write = 0;
string_set(model->sample_write, "0 spl.");
return true;
});
//SubghzReadRAW* instance = context;
}
void subghz_read_raw_exit(void* context) {
@ -223,10 +366,6 @@ void subghz_read_raw_exit(void* context) {
instance->callback(SubghzCustomEventViewReadRAWIDLE, instance->context);
model->satus = SubghzReadRAWStatusStart;
}
string_reset(model->frequency_str);
string_reset(model->preset_str);
string_reset(model->sample_write);
free(model->rssi_history);
return true;
});
}
@ -248,6 +387,7 @@ SubghzReadRAW* subghz_read_raw_alloc() {
string_init(model->frequency_str);
string_init(model->preset_str);
string_init(model->sample_write);
model->rssi_history = furi_alloc(SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t));
return true;
});
@ -262,6 +402,7 @@ void subghz_read_raw_free(SubghzReadRAW* instance) {
string_clear(model->frequency_str);
string_clear(model->preset_str);
string_clear(model->sample_write);
free(model->rssi_history);
return true;
});
view_free(instance->view);

View file

@ -7,6 +7,14 @@ typedef struct SubghzReadRAW SubghzReadRAW;
typedef void (*SubghzReadRAWCallback)(SubghzCustomEvent event, void* context);
typedef enum {
SubghzReadRAWStatusStart,
SubghzReadRAWStatusIDLE,
SubghzReadRAWStatusREC,
SubghzReadRAWStatusTX,
SubghzReadRAWStatusTXRepeat,
} SubghzReadRAWStatus;
void subghz_read_raw_set_callback(
SubghzReadRAW* subghz_read_raw,
SubghzReadRAWCallback callback,
@ -23,6 +31,12 @@ void subghz_read_raw_add_data_statusbar(
void subghz_read_raw_update_sample_write(SubghzReadRAW* instance, size_t sample);
void subghz_read_raw_stop_send(SubghzReadRAW* instance);
void subghz_read_raw_update_sin(SubghzReadRAW* instance);
void subghz_read_raw_add_data_rssi(SubghzReadRAW* instance, float rssi);
void subghz_read_raw_set_status(SubghzReadRAW* instance, SubghzReadRAWStatus satus);
View* subghz_read_raw_get_view(SubghzReadRAW* subghz_static);

View file

@ -469,7 +469,7 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
case FuriHalVersionRegionEuRu:
//433,05..434,79; 868,15..868,55
if(!(value >= 433050000 && value <= 434790000) &&
!(value >= 868150000 && value <= 8680550000)) {
!(value >= 868150000 && value <= 868550000)) {
} else {
txrx = true;
}

View file

@ -469,7 +469,7 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
case FuriHalVersionRegionEuRu:
//433,05..434,79; 868,15..868,55
if(!(value >= 433050000 && value <= 434790000) &&
!(value >= 868150000 && value <= 8680550000)) {
!(value >= 868150000 && value <= 868550000)) {
} else {
txrx = true;
}

View file

@ -17,6 +17,8 @@ struct SubGhzProtocolRAW {
string_t file_name;
size_t sample_write;
bool last_level;
SubGhzProtocolRAWCallbackEnd callback_end;
void* context_end;
};
typedef enum {
@ -65,6 +67,22 @@ void subghz_protocol_raw_free(SubGhzProtocolRAW* instance) {
free(instance);
}
void subghz_protocol_raw_file_encoder_worker_callback_end(void* context) {
furi_assert(context);
SubGhzProtocolRAW* instance = context;
if(instance->callback_end) instance->callback_end(instance->context_end);
}
void subghz_protocol_raw_file_encoder_worker_set_callback_end(
SubGhzProtocolRAW* instance,
SubGhzProtocolRAWCallbackEnd callback_end,
void* context_end) {
furi_assert(instance);
furi_assert(callback_end);
instance->callback_end = callback_end;
instance->context_end = context_end;
}
void subghz_protocol_raw_file_encoder_worker_stop(void* context) {
furi_assert(context);
SubGhzProtocolRAW* instance = context;
@ -90,10 +108,17 @@ bool subghz_protocol_raw_send_key(
//the worker needs a file in order to open and read part of the file
osDelay(100);
instance->file_is_open = RAWFileIsOpenRead;
//Forwarding UPLOAD to common encoder
subghz_protocol_encoder_common_set_callback(
encoder, subghz_file_encoder_worker_get_level_duration, instance->file_worker_encoder);
//forced stop of transmission
subghz_protocol_encoder_common_set_callback_end(
encoder, subghz_protocol_raw_file_encoder_worker_stop, instance);
//file transfer complete callback
subghz_file_encoder_worker_callback_end(
instance->file_worker_encoder,
subghz_protocol_raw_file_encoder_worker_callback_end,
instance);
loaded = true;
} else {
@ -187,7 +212,8 @@ bool subghz_protocol_raw_save_to_file_init(
break;
}
if(!flipper_file_write_string_cstr(instance->flipper_file, "Protocol", instance->common.name)) {
if(!flipper_file_write_string_cstr(
instance->flipper_file, "Protocol", instance->common.name)) {
FURI_LOG_E(TAG, "Unable to add Protocol");
break;
}

View file

@ -2,6 +2,8 @@
#include "subghz_protocol_common.h"
typedef void (*SubGhzProtocolRAWCallbackEnd)(void* context);
typedef struct SubGhzProtocolRAW SubGhzProtocolRAW;
/** Allocate SubGhzProtocolRAW
@ -16,6 +18,11 @@ SubGhzProtocolRAW* subghz_protocol_raw_alloc();
*/
void subghz_protocol_raw_free(SubGhzProtocolRAW* instance);
void subghz_protocol_raw_file_encoder_worker_set_callback_end(
SubGhzProtocolRAW* instance,
SubGhzProtocolRAWCallbackEnd callback_end,
void* context_end);
/** Reset internal state
* @param instance - SubGhzProtocolRAW instance
*/

View file

@ -16,12 +16,26 @@ struct SubGhzFileEncoderWorker {
FlipperFile* flipper_file;
volatile bool worker_running;
volatile bool worker_stoping;
bool level;
int32_t duration;
string_t str_data;
string_t file_path;
SubGhzFileEncoderWorkerCallbackEnd callback_end;
void* context_end;
};
void subghz_file_encoder_worker_callback_end(
SubGhzFileEncoderWorker* instance,
SubGhzFileEncoderWorkerCallbackEnd callback_end,
void* context_end) {
furi_assert(instance);
furi_assert(callback_end);
instance->callback_end = callback_end;
instance->context_end = context_end;
}
void subghz_file_encoder_worker_add_livel_duration(
SubGhzFileEncoderWorker* instance,
int32_t duration) {
@ -89,6 +103,7 @@ LevelDuration subghz_file_encoder_worker_get_level_duration(void* context) {
} else if(duration == 0) {
level_duration = level_duration_reset();
FURI_LOG_I(TAG, "Stop transmission");
instance->worker_stoping = true;
}
return level_duration;
} else {
@ -111,9 +126,7 @@ static int32_t subghz_file_encoder_worker_thread(void* context) {
if(!flipper_file_open_existing(
instance->flipper_file, string_get_cstr(instance->file_path))) {
FURI_LOG_E(
TAG,
"Unable to open file for read: %s",
string_get_cstr(instance->file_path));
TAG, "Unable to open file for read: %s", string_get_cstr(instance->file_path));
break;
}
if(!flipper_file_read_string(instance->flipper_file, "Protocol", instance->str_data)) {
@ -124,6 +137,7 @@ static int32_t subghz_file_encoder_worker_thread(void* context) {
//skip the end of the previous line "\n"
storage_file_seek(file, 1, false);
res = true;
instance->worker_stoping = false;
FURI_LOG_I(TAG, "Start transmission");
} while(0);
@ -152,7 +166,11 @@ static int32_t subghz_file_encoder_worker_thread(void* context) {
}
//waiting for the end of the transfer
FURI_LOG_I(TAG, "End read file");
while(instance->worker_running) {
if(instance->worker_stoping) {
if(instance->callback_end) instance->callback_end(instance->context_end);
}
osDelay(50);
}
flipper_file_close(instance->flipper_file);
@ -177,6 +195,7 @@ SubGhzFileEncoderWorker* subghz_file_encoder_worker_alloc() {
string_init(instance->str_data);
string_init(instance->file_path);
instance->level = false;
instance->worker_stoping = true;
return instance;
}

View file

@ -2,8 +2,20 @@
#include <furi-hal.h>
typedef void (*SubGhzFileEncoderWorkerCallbackEnd)(void* context);
typedef struct SubGhzFileEncoderWorker SubGhzFileEncoderWorker;
/** End callback SubGhzWorker
*
* @param instance SubGhzFileEncoderWorker instance
* @param callback SubGhzFileEncoderWorkerCallbackEnd callback
*/
void subghz_file_encoder_worker_callback_end(
SubGhzFileEncoderWorker* instance,
SubGhzFileEncoderWorkerCallbackEnd callback_end,
void* context_end);
/** Allocate SubGhzFileEncoderWorker
*
* @return SubGhzFileEncoderWorker*