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

re-implemented auto-detect raw #152

Merged
merged 2 commits into from
Aug 2, 2022
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
8 changes: 7 additions & 1 deletion applications/subghz/scenes/subghz_scene_read_raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,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 @@ -339,4 +345,4 @@ void subghz_scene_read_raw_on_exit(void* context) {

//filter restoration
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable);
}
}
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 All @@ -17,6 +20,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_next_frequency(const uint32_t value, void* context) {
furi_assert(context);
SubGhz* subghz = context;
Expand Down Expand Up @@ -67,6 +80,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 @@ -99,6 +126,18 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
subghz_setting_get_preset_data_size(subghz->setting, 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 @@ -193,6 +232,20 @@ void subghz_scene_receiver_config_on_enter(void* context) {
variable_item_set_current_value_text(
item, subghz_setting_get_preset_name(subghz->setting, 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
15 changes: 14 additions & 1 deletion applications/subghz/subghz_history.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,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",
preset->frequency / 1000000 % 1000,
preset->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
1 change: 1 addition & 0 deletions 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
162 changes: 149 additions & 13 deletions lib/subghz/protocols/raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@
#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_DOWNLOAD_MAX_SIZE 2048
#define SUBGHZ_AUTO_DETECT_RAW_THRESHOLD -72.0f
#define SUBGHZ_AUTO_DETECT_RAW_POSTROLL_FRAMES 30

static const SubGhzBlockConst subghz_protocol_raw_const = {
.te_short = 50,
Expand All @@ -24,6 +29,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 +39,9 @@ struct SubGhzProtocolDecoderRAW {
string_t file_name;
size_t sample_write;
bool last_level;
bool auto_mode;
bool has_rssi_above_threshold;
uint8_t postroll_frames;
};

struct SubGhzProtocolEncoderRAW {
Expand All @@ -55,8 +65,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,
.deserialize = subghz_protocol_decoder_raw_deserialize,
.get_string = subghz_protocol_decoder_raw_get_string,
};
Expand Down Expand Up @@ -198,6 +208,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_AUTO_DETECT_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 @@ -210,6 +239,7 @@ void* subghz_protocol_decoder_raw_alloc(SubGhzEnvironment* environment) {
instance->ind_write = 0;
instance->last_level = false;
instance->file_is_open = RAWFileIsOpenClose;
instance->postroll_frames = 0;
string_init(instance->file_name);

return instance;
Expand All @@ -219,48 +249,92 @@ 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;
instance->postroll_frames = 0;
}

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

bool wrote_data = false;

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);
wrote_data = true;
}

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

return false;
}

return wrote_data;
}

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->upload_raw != NULL && duration > subghz_protocol_raw_const.te_short) {
if (instance->auto_mode) {
float rssi = furi_hal_subghz_get_rssi();
if (rssi >= SUBGHZ_AUTO_DETECT_RAW_THRESHOLD) {
subghz_protocol_decoder_raw_write_data(context, level, duration);
instance->has_rssi_above_threshold = true;
instance->postroll_frames = 0;
} else if (instance->has_rssi_above_threshold) {
subghz_protocol_decoder_raw_write_data(instance, level, duration);
instance->postroll_frames++;

if (instance->postroll_frames >= SUBGHZ_AUTO_DETECT_RAW_POSTROLL_FRAMES) {
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
}
}
} else {
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_write(instance);
}
}
}
}

bool subghz_protocol_decoder_raw_deserialize(void* context, FlipperFormat* flipper_format) {
uint8_t subghz_protocol_decoder_raw_get_hash_data(void* context) {
furi_assert(context);
UNUSED(context);
UNUSED(flipper_format);
//ToDo stub, for backwards compatibility
return true;
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;
UNUSED(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 @@ -330,6 +404,68 @@ 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,
SubGhzPresetDefinition* 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_RAW_FILE_TYPE, SUBGHZ_RAW_FILE_VERSION)) {
FURI_LOG_E(TAG, "Unable to add header");
break;
}

if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) {
FURI_LOG_E(TAG, "Unable to add Frequency");
break;
}
subghz_block_generic_get_preset_name(string_get_cstr(preset->name), temp_str);
if(!flipper_format_write_string_cstr(
flipper_format, "Preset", string_get_cstr(temp_str))) {
FURI_LOG_E(TAG, "Unable to add Preset");
break;
}
if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
if(!flipper_format_write_string_cstr(
flipper_format, "Custom_preset_module", "CC1101")) {
FURI_LOG_E(TAG, "Unable to add Custom_preset_module");
break;
}
if(!flipper_format_write_hex(
flipper_format, "Custom_preset_data", preset->data, preset->data_size)) {
FURI_LOG_E(TAG, "Unable to add Custom_preset_data");
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