Skip to content

Commit 0c1f8bb

Browse files
authored
Merge pull request #79 from perspecdev/auto-detect-raw-unleashed
Auto detect raw unleashed
2 parents 04cf0e8 + 2892393 commit 0c1f8bb

File tree

9 files changed

+264
-16
lines changed

9 files changed

+264
-16
lines changed

applications/subghz/scenes/subghz_scene_read_raw.c

+8-2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ void subghz_scene_read_raw_on_enter(void* context) {
100100
subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME);
101101
furi_assert(subghz->txrx->decoder_result);
102102

103+
// make sure we're not in auto-detect mode, which is only meant for the Read app
104+
subghz_protocol_decoder_raw_set_auto_mode(
105+
subghz->txrx->decoder_result,
106+
false
107+
);
108+
103109
//set filter RAW feed
104110
subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_RAW);
105111
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReadRAW);
@@ -243,7 +249,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
243249

244250
string_t temp_str;
245251
string_init(temp_str);
246-
252+
247253
uint32_t time = LL_RTC_TIME_Get(RTC); // 0x00HHMMSS
248254
uint32_t date = LL_RTC_DATE_Get(RTC); // 0xWWDDMMYY
249255
char strings[1][25];
@@ -254,7 +260,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
254260
, __LL_RTC_CONVERT_BCD2BIN((time >> 16) & 0xFF) // HOUR
255261
, __LL_RTC_CONVERT_BCD2BIN((time >> 8) & 0xFF) // DAY
256262
);
257-
263+
258264
string_printf(
259265
temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, strings[0], SUBGHZ_APP_EXTENSION);
260266
subghz_protocol_raw_gen_fff_data(subghz->txrx->fff_data, string_get_cstr(temp_str));

applications/subghz/scenes/subghz_scene_receiver_config.c

+53
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#include "../subghz_i.h"
22

3+
#include <lib/subghz/protocols/raw.h>
4+
35
enum SubGhzSettingIndex {
46
SubGhzSettingIndexFrequency,
57
SubGhzSettingIndexHopping,
68
SubGhzSettingIndexModulation,
9+
SubGhzSettingIndexDetectRaw,
710
SubGhzSettingIndexLock,
811
};
912

@@ -31,6 +34,16 @@ const uint32_t hopping_value[HOPPING_COUNT] = {
3134
SubGhzHopperStateRunnig,
3235
};
3336

37+
#define DETECT_RAW_COUNT 2
38+
const char* const detect_raw_text[DETECT_RAW_COUNT] = {
39+
"OFF",
40+
"ON",
41+
};
42+
const SubGhzProtocolFlag detect_raw_value[DETECT_RAW_COUNT] = {
43+
SubGhzProtocolFlag_Decodable,
44+
SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_RAW,
45+
};
46+
3447
uint8_t subghz_scene_receiver_config_uint32_value_index(
3548
const uint32_t value,
3649
const uint32_t values[],
@@ -82,6 +95,20 @@ uint8_t subghz_scene_receiver_config_hopper_value_index(
8295
}
8396
}
8497

98+
uint8_t subghz_scene_receiver_config_detect_raw_value_index(
99+
const SubGhzProtocolFlag value,
100+
const SubGhzProtocolFlag values[],
101+
uint8_t values_count) {
102+
uint8_t index = 0;
103+
for(uint8_t i = 0; i < values_count; i++) {
104+
if(value == values[i]) {
105+
index = i;
106+
break;
107+
}
108+
}
109+
return index;
110+
}
111+
85112
static void subghz_scene_receiver_config_set_frequency(VariableItem* item) {
86113
SubGhz* subghz = variable_item_get_context(item);
87114
uint8_t index = variable_item_get_current_value_index(item);
@@ -109,6 +136,18 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) {
109136
subghz->txrx->preset = preset_value[index];
110137
}
111138

139+
static void subghz_scene_receiver_config_set_detect_raw(VariableItem* item) {
140+
SubGhz* subghz = variable_item_get_context(item);
141+
uint8_t index = variable_item_get_current_value_index(item);
142+
143+
variable_item_set_current_value_text(item, detect_raw_text[index]);
144+
subghz_receiver_set_filter(subghz->txrx->receiver, detect_raw_value[index]);
145+
subghz_protocol_decoder_raw_set_auto_mode(
146+
subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME),
147+
(index == 1)
148+
);
149+
}
150+
112151
static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) {
113152
SubGhz* subghz = variable_item_get_context(item);
114153
uint8_t index = variable_item_get_current_value_index(item);
@@ -201,6 +240,20 @@ void subghz_scene_receiver_config_on_enter(void* context) {
201240
variable_item_set_current_value_index(item, value_index);
202241
variable_item_set_current_value_text(item, preset_text[value_index]);
203242

243+
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
244+
SubGhzCustomEventManagerSet) {
245+
item = variable_item_list_add(
246+
subghz->variable_item_list,
247+
"Detect Raw:",
248+
DETECT_RAW_COUNT,
249+
subghz_scene_receiver_config_set_detect_raw,
250+
subghz);
251+
value_index = subghz_scene_receiver_config_detect_raw_value_index(
252+
subghz_receiver_get_filter(subghz->txrx->receiver), detect_raw_value, DETECT_RAW_COUNT);
253+
variable_item_set_current_value_index(item, value_index);
254+
variable_item_set_current_value_text(item, detect_raw_text[value_index]);
255+
}
256+
204257
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
205258
SubGhzCustomEventManagerSet) {
206259
variable_item_list_add(subghz->variable_item_list, "Lock Keyboard", 1, NULL, NULL);

applications/subghz/scenes/subghz_scene_receiver_info.c

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ void subghz_scene_receiver_info_on_enter(void* context) {
8989
// Removed static check
9090
if(((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) ==
9191
SubGhzProtocolFlag_Send) &&
92+
// disable "Send" for auto-captured RAW signals for now. They can still be saved and sent by loading them.
93+
subghz->txrx->decoder_result->protocol->type != SubGhzProtocolTypeRAW &&
9294
subghz->txrx->decoder_result->protocol->encoder->deserialize) {
9395
widget_add_button_element(
9496
subghz->widget,

applications/subghz/subghz_history.c

+14-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,20 @@ bool subghz_history_add_to_history(
168168
FURI_LOG_E(TAG, "Missing Protocol");
169169
break;
170170
}
171-
if(!strcmp(string_get_cstr(instance->tmp_string), "KeeLoq")) {
171+
if(!strcmp(string_get_cstr(instance->tmp_string), "RAW")) {
172+
string_printf(
173+
item->item_str,
174+
"RAW %03ld.%02ld",
175+
frequency / 1000000 % 1000,
176+
frequency / 10000 % 100);
177+
178+
if(!flipper_format_rewind(item->flipper_string)) {
179+
FURI_LOG_E(TAG, "Rewind error");
180+
}
181+
182+
break;
183+
}
184+
else if(!strcmp(string_get_cstr(instance->tmp_string), "KeeLoq")) {
172185
string_set_str(instance->tmp_string, "KL ");
173186
if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) {
174187
FURI_LOG_E(TAG, "Missing Protocol");

applications/subghz/views/receiver.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ static const Icon* ReceiverItemIcons[] = {
3333
[SubGhzProtocolTypeUnknown] = &I_Quest_7x8,
3434
[SubGhzProtocolTypeStatic] = &I_Unlock_7x8,
3535
[SubGhzProtocolTypeDynamic] = &I_Lock_7x8,
36+
[SubGhzProtocolTypeRAW] = &I_Unlock_7x8,
3637
};
3738

3839
typedef enum {
@@ -426,4 +427,4 @@ void subghz_view_receiver_set_idx_menu(SubGhzViewReceiver* subghz_receiver, uint
426427
return true;
427428
});
428429
subghz_view_receiver_update_offset(subghz_receiver);
429-
}
430+
}

lib/subghz/protocols/raw.c

+133-10
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
#include "../blocks/generic.h"
99
#include "../blocks/math.h"
1010

11+
#include <furi.h>
1112
#include <flipper_format/flipper_format_i.h>
1213
#include <lib/toolbox/stream/stream.h>
14+
#include <stm32wbxx_ll_rtc.h>
1315

1416
#define TAG "SubGhzProtocolRAW"
1517
#define SUBGHZ_DOWNLOAD_MAX_SIZE 512
18+
#define SUBGHZ_AUTO_DETECT_RAW_THRESHOLD -72.0f
1619

1720
static const SubGhzBlockConst subghz_protocol_raw_const = {
1821
.te_short = 50,
@@ -24,6 +27,8 @@ static const SubGhzBlockConst subghz_protocol_raw_const = {
2427
struct SubGhzProtocolDecoderRAW {
2528
SubGhzProtocolDecoderBase base;
2629

30+
SubGhzBlockDecoder decoder;
31+
2732
int32_t* upload_raw;
2833
uint16_t ind_write;
2934
Storage* storage;
@@ -32,6 +37,8 @@ struct SubGhzProtocolDecoderRAW {
3237
string_t file_name;
3338
size_t sample_write;
3439
bool last_level;
40+
bool auto_mode;
41+
bool has_rssi_above_threshold;
3542
};
3643

3744
struct SubGhzProtocolEncoderRAW {
@@ -55,8 +62,8 @@ const SubGhzProtocolDecoder subghz_protocol_raw_decoder = {
5562
.feed = subghz_protocol_decoder_raw_feed,
5663
.reset = subghz_protocol_decoder_raw_reset,
5764

58-
.get_hash_data = NULL,
59-
.serialize = NULL,
65+
.get_hash_data = subghz_protocol_decoder_raw_get_hash_data,
66+
.serialize = subghz_protocol_decoder_raw_serialize,
6067
.get_string = subghz_protocol_decoder_raw_get_string,
6168
};
6269

@@ -187,6 +194,25 @@ void subghz_protocol_raw_save_to_file_stop(SubGhzProtocolDecoderRAW* instance) {
187194
instance->file_is_open = RAWFileIsOpenClose;
188195
}
189196

197+
void subghz_protocol_decoder_raw_set_auto_mode(void* context, bool auto_mode) {
198+
furi_assert(context);
199+
SubGhzProtocolDecoderRAW* instance = context;
200+
instance->auto_mode = auto_mode;
201+
202+
if (auto_mode) {
203+
if (instance->upload_raw == NULL) {
204+
instance->upload_raw = malloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(int32_t));
205+
}
206+
} else {
207+
if (instance->upload_raw != NULL) {
208+
free(instance->upload_raw);
209+
instance->upload_raw = NULL;
210+
}
211+
}
212+
213+
subghz_protocol_decoder_raw_reset(context);
214+
}
215+
190216
size_t subghz_protocol_raw_get_sample_write(SubGhzProtocolDecoderRAW* instance) {
191217
return instance->sample_write + instance->ind_write;
192218
}
@@ -208,39 +234,84 @@ void subghz_protocol_decoder_raw_free(void* context) {
208234
furi_assert(context);
209235
SubGhzProtocolDecoderRAW* instance = context;
210236
string_clear(instance->file_name);
237+
if (instance->upload_raw != NULL) {
238+
free(instance->upload_raw);
239+
instance->upload_raw = NULL;
240+
}
211241
free(instance);
212242
}
213243

214244
void subghz_protocol_decoder_raw_reset(void* context) {
215245
furi_assert(context);
216246
SubGhzProtocolDecoderRAW* instance = context;
217247
instance->ind_write = 0;
248+
instance->has_rssi_above_threshold = false;
218249
instance->last_level = false;
219250
}
220251

252+
void subghz_protocol_decoder_raw_write_data(void* context, bool level, uint32_t duration) {
253+
furi_assert(context);
254+
SubGhzProtocolDecoderRAW* instance = context;
255+
256+
if(instance->last_level != level) {
257+
instance->last_level = (level ? true : false);
258+
instance->upload_raw[instance->ind_write++] = (level ? duration : -duration);
259+
subghz_protocol_blocks_add_bit(&instance->decoder, (level) ? 1 : 0);
260+
}
261+
262+
if(instance->ind_write == SUBGHZ_DOWNLOAD_MAX_SIZE) {
263+
if(instance->base.callback)
264+
instance->base.callback(&instance->base, instance->base.context);
265+
}
266+
}
267+
221268
void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t duration) {
222269
furi_assert(context);
223270
SubGhzProtocolDecoderRAW* instance = context;
224271

225272
if(instance->upload_raw != NULL) {
226-
if(duration > subghz_protocol_raw_const.te_short) {
227-
if(instance->last_level != level) {
228-
instance->last_level = (level ? true : false);
229-
instance->upload_raw[instance->ind_write++] = (level ? duration : -duration);
273+
if (instance->auto_mode) {
274+
float rssi = furi_hal_subghz_get_rssi();
275+
if (rssi >= SUBGHZ_AUTO_DETECT_RAW_THRESHOLD && duration >= subghz_protocol_raw_const.te_short) {
276+
subghz_protocol_decoder_raw_write_data(context, level, duration);
277+
instance->has_rssi_above_threshold = true;
278+
} else if (instance->has_rssi_above_threshold) {
279+
subghz_protocol_decoder_raw_write_data(instance, level, duration);
280+
281+
if ((!level) && (DURATION_DIFF(duration, subghz_protocol_raw_const.te_long)) >
282+
subghz_protocol_raw_const.te_long * 7) {
283+
if(instance->base.callback)
284+
instance->base.callback(&instance->base, instance->base.context);
285+
}
286+
}
287+
} else {
288+
if(duration > subghz_protocol_raw_const.te_short) {
289+
if(instance->last_level != level) {
290+
instance->last_level = (level ? true : false);
291+
instance->upload_raw[instance->ind_write++] = (level ? duration : -duration);
292+
subghz_protocol_blocks_add_bit(&instance->decoder, (level) ? 1 : 0);
293+
}
230294
}
231-
}
232295

233-
if(instance->ind_write == SUBGHZ_DOWNLOAD_MAX_SIZE) {
234-
subghz_protocol_raw_save_to_file_write(instance);
296+
if(instance->ind_write == SUBGHZ_DOWNLOAD_MAX_SIZE) {
297+
subghz_protocol_raw_save_to_file_stop(instance);
298+
}
235299
}
236300
}
237301
}
238302

303+
uint8_t subghz_protocol_decoder_raw_get_hash_data(void* context) {
304+
furi_assert(context);
305+
SubGhzProtocolDecoderRAW* instance = context;
306+
return subghz_protocol_blocks_get_hash_data(
307+
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
308+
}
309+
239310
void subghz_protocol_decoder_raw_get_string(void* context, string_t output) {
240311
furi_assert(context);
241312
//SubGhzProtocolDecoderRAW* instance = context;
242313
//ToDo no use
243-
string_cat_printf(output, "RAW Date");
314+
string_cat_printf(output, "RAW Data");
244315
}
245316

246317
void* subghz_protocol_encoder_raw_alloc(SubGhzEnvironment* environment) {
@@ -310,6 +381,58 @@ void subghz_protocol_raw_gen_fff_data(FlipperFormat* flipper_format, const char*
310381
} while(false);
311382
}
312383

384+
bool subghz_protocol_decoder_raw_serialize(
385+
void* context,
386+
FlipperFormat* flipper_format,
387+
uint32_t frequency,
388+
FuriHalSubGhzPreset preset) {
389+
furi_assert(context);
390+
SubGhzProtocolDecoderRAW* instance = context;
391+
if (instance->auto_mode) {
392+
furi_assert(instance);
393+
bool res = false;
394+
string_t temp_str;
395+
string_init(temp_str);
396+
397+
do {
398+
stream_clean(flipper_format_get_raw_stream(flipper_format));
399+
if(!flipper_format_write_header_cstr(
400+
flipper_format, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) {
401+
FURI_LOG_E(TAG, "Unable to add header");
402+
break;
403+
}
404+
405+
if(!flipper_format_write_uint32(flipper_format, "Frequency", &frequency, 1)) {
406+
FURI_LOG_E(TAG, "Unable to add Frequency");
407+
break;
408+
}
409+
if(!subghz_block_generic_get_preset_name(preset, temp_str)) {
410+
break;
411+
}
412+
if(!flipper_format_write_string_cstr(flipper_format, "Preset", string_get_cstr(temp_str))) {
413+
FURI_LOG_E(TAG, "Unable to add Preset");
414+
break;
415+
}
416+
if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->base.protocol->name)) {
417+
FURI_LOG_E(TAG, "Unable to add Protocol");
418+
break;
419+
}
420+
421+
if (!flipper_format_write_int32(flipper_format, "RAW_Data", instance->upload_raw, instance->ind_write)) {
422+
FURI_LOG_E(TAG, "Unable to add Raw Data");
423+
break;
424+
} else {
425+
instance->ind_write = 0;
426+
}
427+
res = true;
428+
} while(false);
429+
string_clear(temp_str);
430+
return res;
431+
} else {
432+
return false;
433+
}
434+
}
435+
313436
bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipper_format) {
314437
furi_assert(context);
315438
SubGhzProtocolEncoderRAW* instance = context;

0 commit comments

Comments
 (0)