Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto detect raw unleashed #79

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions applications/subghz/scenes/subghz_scene_read_raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ void subghz_scene_read_raw_on_enter(void* context) {
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME);
furi_assert(subghz->txrx->decoder_result);

// make sure we're not in auto-detect mode, which is only meant for the Read app
subghz_protocol_decoder_raw_set_auto_mode(
subghz->txrx->decoder_result,
false
);

//set filter RAW feed
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_RAW);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReadRAW);
Expand Down Expand Up @@ -243,7 +249,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {

string_t temp_str;
string_init(temp_str);

uint32_t time = LL_RTC_TIME_Get(RTC); // 0x00HHMMSS
uint32_t date = LL_RTC_DATE_Get(RTC); // 0xWWDDMMYY
char strings[1][25];
Expand All @@ -254,7 +260,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
, __LL_RTC_CONVERT_BCD2BIN((time >> 16) & 0xFF) // HOUR
, __LL_RTC_CONVERT_BCD2BIN((time >> 8) & 0xFF) // DAY
);

string_printf(
temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, strings[0], SUBGHZ_APP_EXTENSION);
subghz_protocol_raw_gen_fff_data(subghz->txrx->fff_data, string_get_cstr(temp_str));
Expand Down
53 changes: 53 additions & 0 deletions applications/subghz/scenes/subghz_scene_receiver_config.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "../subghz_i.h"

#include <lib/subghz/protocols/raw.h>

enum SubGhzSettingIndex {
SubGhzSettingIndexFrequency,
SubGhzSettingIndexHopping,
SubGhzSettingIndexModulation,
SubGhzSettingIndexDetectRaw,
SubGhzSettingIndexLock,
};

Expand Down Expand Up @@ -31,6 +34,16 @@ const uint32_t hopping_value[HOPPING_COUNT] = {
SubGhzHopperStateRunnig,
};

#define DETECT_RAW_COUNT 2
const char* const detect_raw_text[DETECT_RAW_COUNT] = {
"OFF",
"ON",
};
const SubGhzProtocolFlag detect_raw_value[DETECT_RAW_COUNT] = {
SubGhzProtocolFlag_Decodable,
SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW,
};

uint8_t subghz_scene_receiver_config_uint32_value_index(
const uint32_t value,
const uint32_t values[],
Expand Down Expand Up @@ -82,6 +95,20 @@ uint8_t subghz_scene_receiver_config_hopper_value_index(
}
}

uint8_t subghz_scene_receiver_config_detect_raw_value_index(
const SubGhzProtocolFlag value,
const SubGhzProtocolFlag values[],
uint8_t values_count) {
uint8_t index = 0;
for(uint8_t i = 0; i < values_count; i++) {
if(value == values[i]) {
index = i;
break;
}
}
return index;
}

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);
Expand Down Expand Up @@ -109,6 +136,18 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
subghz->txrx->preset = preset_value[index];
}

static void subghz_scene_receiver_config_set_detect_raw(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, detect_raw_text[index]);
subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]);
subghz_protocol_decoder_raw_set_auto_mode(
subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
(index == 1)
);
}

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);
Expand Down Expand Up @@ -201,6 +240,20 @@ void subghz_scene_receiver_config_on_enter(void* context) {
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, preset_text[value_index]);

if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
item = variable_item_list_add(
subghz->variable_item_list,
"Detect Raw:",
DETECT_RAW_COUNT,
subghz_scene_receiver_config_set_detect_raw,
subghz);
value_index = subghz_scene_receiver_config_detect_raw_value_index(
subghz_receiver_get_filter(subghz->txrx->receiver), detect_raw_value, DETECT_RAW_COUNT);
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, detect_raw_text[value_index]);
}

if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
SubGhzCustomEventManagerSet) {
variable_item_list_add(subghz->variable_item_list, "Lock Keyboard", 1, NULL, NULL);
Expand Down
2 changes: 2 additions & 0 deletions applications/subghz/scenes/subghz_scene_receiver_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ void subghz_scene_receiver_info_on_enter(void* context) {
// Removed static check
if(((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) ==
SubGhzProtocolFlag_Send) &&
// disable "Send" for auto-captured RAW signals for now. They can still be saved and sent by loading them.
subghz->txrx->decoder_result->protocol->type != SubGhzProtocolTypeRAW &&
subghz->txrx->decoder_result->protocol->encoder->deserialize) {
widget_add_button_element(
subghz->widget,
Expand Down
15 changes: 14 additions & 1 deletion applications/subghz/subghz_history.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,20 @@ bool subghz_history_add_to_history(
FURI_LOG_E(TAG, "Missing Protocol");
break;
}
if(!strcmp(string_get_cstr(instance->tmp_string), "KeeLoq")) {
if(!strcmp(string_get_cstr(instance->tmp_string), "RAW")) {
string_printf(
item->item_str,
"RAW %03ld.%02ld",
frequency / 1000000 % 1000,
frequency / 10000 % 100);

if(!flipper_format_rewind(item->flipper_string)) {
FURI_LOG_E(TAG, "Rewind error");
}

break;
}
else if(!strcmp(string_get_cstr(instance->tmp_string), "KeeLoq")) {
string_set_str(instance->tmp_string, "KL ");
if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) {
FURI_LOG_E(TAG, "Missing Protocol");
Expand Down
3 changes: 2 additions & 1 deletion applications/subghz/views/receiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ static const Icon* ReceiverItemIcons[] = {
[SubGhzProtocolTypeUnknown] = &I_Quest_7x8,
[SubGhzProtocolTypeStatic] = &I_Unlock_7x8,
[SubGhzProtocolTypeDynamic] = &I_Lock_7x8,
[SubGhzProtocolTypeRAW] = &I_Unlock_7x8,
};

typedef enum {
Expand Down Expand Up @@ -426,4 +427,4 @@ void subghz_view_receiver_set_idx_menu(SubGhzViewReceiver* subghz_receiver, uint
return true;
});
subghz_view_receiver_update_offset(subghz_receiver);
}
}
143 changes: 133 additions & 10 deletions lib/subghz/protocols/raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
#include "../blocks/generic.h"
#include "../blocks/math.h"

#include <furi.h>
#include <flipper_format/flipper_format_i.h>
#include <lib/toolbox/stream/stream.h>
#include <stm32wbxx_ll_rtc.h>

#define TAG "SubGhzProtocolRAW"
#define SUBGHZ_DOWNLOAD_MAX_SIZE 512
#define SUBGHZ_AUTO_DETECT_RAW_THRESHOLD -72.0f

static const SubGhzBlockConst subghz_protocol_raw_const = {
.te_short = 50,
Expand All @@ -24,6 +27,8 @@ static const SubGhzBlockConst subghz_protocol_raw_const = {
struct SubGhzProtocolDecoderRAW {
SubGhzProtocolDecoderBase base;

SubGhzBlockDecoder decoder;

int32_t* upload_raw;
uint16_t ind_write;
Storage* storage;
Expand All @@ -32,6 +37,8 @@ struct SubGhzProtocolDecoderRAW {
string_t file_name;
size_t sample_write;
bool last_level;
bool auto_mode;
bool has_rssi_above_threshold;
};

struct SubGhzProtocolEncoderRAW {
Expand All @@ -55,8 +62,8 @@ const SubGhzProtocolDecoder subghz_protocol_raw_decoder = {
.feed = subghz_protocol_decoder_raw_feed,
.reset = subghz_protocol_decoder_raw_reset,

.get_hash_data = NULL,
.serialize = NULL,
.get_hash_data = subghz_protocol_decoder_raw_get_hash_data,
.serialize = subghz_protocol_decoder_raw_serialize,
.get_string = subghz_protocol_decoder_raw_get_string,
};

Expand Down Expand Up @@ -187,6 +194,25 @@ void subghz_protocol_raw_save_to_file_stop(SubGhzProtocolDecoderRAW* instance) {
instance->file_is_open = RAWFileIsOpenClose;
}

void subghz_protocol_decoder_raw_set_auto_mode(void* context, bool auto_mode) {
furi_assert(context);
SubGhzProtocolDecoderRAW* instance = context;
instance->auto_mode = auto_mode;

if (auto_mode) {
if (instance->upload_raw == NULL) {
instance->upload_raw = malloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(int32_t));
}
} else {
if (instance->upload_raw != NULL) {
free(instance->upload_raw);
instance->upload_raw = NULL;
}
}

subghz_protocol_decoder_raw_reset(context);
}

size_t subghz_protocol_raw_get_sample_write(SubGhzProtocolDecoderRAW* instance) {
return instance->sample_write + instance->ind_write;
}
Expand All @@ -208,39 +234,84 @@ void subghz_protocol_decoder_raw_free(void* context) {
furi_assert(context);
SubGhzProtocolDecoderRAW* instance = context;
string_clear(instance->file_name);
if (instance->upload_raw != NULL) {
free(instance->upload_raw);
instance->upload_raw = NULL;
}
free(instance);
}

void subghz_protocol_decoder_raw_reset(void* context) {
furi_assert(context);
SubGhzProtocolDecoderRAW* instance = context;
instance->ind_write = 0;
instance->has_rssi_above_threshold = false;
instance->last_level = false;
}

void subghz_protocol_decoder_raw_write_data(void* context, bool level, uint32_t duration) {
furi_assert(context);
SubGhzProtocolDecoderRAW* instance = context;

if(instance->last_level != level) {
instance->last_level = (level ? true : false);
instance->upload_raw[instance->ind_write++] = (level ? duration : -duration);
subghz_protocol_blocks_add_bit(&instance->decoder, (level) ? 1 : 0);
}

if(instance->ind_write == SUBGHZ_DOWNLOAD_MAX_SIZE) {
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
}
}

void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
SubGhzProtocolDecoderRAW* instance = context;

if(instance->upload_raw != NULL) {
if(duration > subghz_protocol_raw_const.te_short) {
if(instance->last_level != level) {
instance->last_level = (level ? true : false);
instance->upload_raw[instance->ind_write++] = (level ? duration : -duration);
if (instance->auto_mode) {
float rssi = furi_hal_subghz_get_rssi();
if (rssi >= SUBGHZ_AUTO_DETECT_RAW_THRESHOLD && duration >= subghz_protocol_raw_const.te_short) {
subghz_protocol_decoder_raw_write_data(context, level, duration);
instance->has_rssi_above_threshold = true;
} else if (instance->has_rssi_above_threshold) {
subghz_protocol_decoder_raw_write_data(instance, level, duration);

if ((!level) && (DURATION_DIFF(duration, subghz_protocol_raw_const.te_long)) >
subghz_protocol_raw_const.te_long * 7) {
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
}
}
} else {
if(duration > subghz_protocol_raw_const.te_short) {
if(instance->last_level != level) {
instance->last_level = (level ? true : false);
instance->upload_raw[instance->ind_write++] = (level ? duration : -duration);
subghz_protocol_blocks_add_bit(&instance->decoder, (level) ? 1 : 0);
}
}
}

if(instance->ind_write == SUBGHZ_DOWNLOAD_MAX_SIZE) {
subghz_protocol_raw_save_to_file_write(instance);
if(instance->ind_write == SUBGHZ_DOWNLOAD_MAX_SIZE) {
subghz_protocol_raw_save_to_file_stop(instance);
}
}
}
}

uint8_t subghz_protocol_decoder_raw_get_hash_data(void* context) {
furi_assert(context);
SubGhzProtocolDecoderRAW* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
}

void subghz_protocol_decoder_raw_get_string(void* context, string_t output) {
furi_assert(context);
//SubGhzProtocolDecoderRAW* instance = context;
//ToDo no use
string_cat_printf(output, "RAW Date");
string_cat_printf(output, "RAW Data");
}

void* subghz_protocol_encoder_raw_alloc(SubGhzEnvironment* environment) {
Expand Down Expand Up @@ -310,6 +381,58 @@ void subghz_protocol_raw_gen_fff_data(FlipperFormat* flipper_format, const char*
} while(false);
}

bool subghz_protocol_decoder_raw_serialize(
void* context,
FlipperFormat* flipper_format,
uint32_t frequency,
FuriHalSubGhzPreset preset) {
furi_assert(context);
SubGhzProtocolDecoderRAW* instance = context;
if (instance->auto_mode) {
furi_assert(instance);
bool res = false;
string_t temp_str;
string_init(temp_str);

do {
stream_clean(flipper_format_get_raw_stream(flipper_format));
if(!flipper_format_write_header_cstr(
flipper_format, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) {
FURI_LOG_E(TAG, "Unable to add header");
break;
}

if(!flipper_format_write_uint32(flipper_format, "Frequency", &frequency, 1)) {
FURI_LOG_E(TAG, "Unable to add Frequency");
break;
}
if(!subghz_block_generic_get_preset_name(preset, temp_str)) {
break;
}
if(!flipper_format_write_string_cstr(flipper_format, "Preset", string_get_cstr(temp_str))) {
FURI_LOG_E(TAG, "Unable to add Preset");
break;
}
if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->base.protocol->name)) {
FURI_LOG_E(TAG, "Unable to add Protocol");
break;
}

if (!flipper_format_write_int32(flipper_format, "RAW_Data", instance->upload_raw, instance->ind_write)) {
FURI_LOG_E(TAG, "Unable to add Raw Data");
break;
} else {
instance->ind_write = 0;
}
res = true;
} while(false);
string_clear(temp_str);
return res;
} else {
return false;
}
}

bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
SubGhzProtocolEncoderRAW* instance = context;
Expand Down
Loading