Merge branch 'dev' of https://github.com/Flipper-XFW/Xtreme-Firmware into xfw-new-app-system

This commit is contained in:
Willy-JL
2023-11-04 21:41:45 +00:00
8 changed files with 653 additions and 8 deletions

View File

@@ -221,7 +221,7 @@ If you like what you're seeing, **please consider donating to us**. We won't eve
- **[Patreon](https://patreon.com/crazyco)**: ❤️ Account needed, subscription with perks across my entire org. - **[Patreon](https://patreon.com/crazyco)**: ❤️ Account needed, subscription with perks across my entire org.
- **[Wire-transfer](https://bunq.me/ClaraK)**: No account needed, one-time - **[Wire-transfer](https://bunq.me/ClaraK)**: No account needed, one-time
- **[Paypal](https://paypal.me/RdX2020)**: Account needed, one-time - **[Paypal](https://paypal.me/ClaraCrazy)**: Account needed, one-time
- **[ko-fi](https://ko-fi.com/cynthialabs)**: No account needed, one-time - **[ko-fi](https://ko-fi.com/cynthialabs)**: No account needed, one-time
- **Monero**: `41kyWeeoVdK4quzQ4M9ikVGs6tCQCLfdx8jLExTNsAu2SF1QAyDqRdjfGM6EL8L9NpXwt89HJeAoGf1aoArk7nDr4AMMV4T` - **Monero**: `41kyWeeoVdK4quzQ4M9ikVGs6tCQCLfdx8jLExTNsAu2SF1QAyDqRdjfGM6EL8L9NpXwt89HJeAoGf1aoArk7nDr4AMMV4T`

View File

@@ -106,7 +106,7 @@ static void subghz_scene_add_to_history_callback(
SubGhz* subghz = context; SubGhz* subghz = context;
// The check can be moved to /lib/subghz/receiver.c, but may result in false positives // The check can be moved to /lib/subghz/receiver.c, but may result in false positives
if((decoder_base->protocol->flag & subghz->ignore_filter) == 0) { if((decoder_base->protocol->filter & subghz->ignore_filter) == 0) {
SubGhzHistory* history = subghz->history; SubGhzHistory* history = subghz->history;
FuriString* item_name = furi_string_alloc(); FuriString* item_name = furi_string_alloc();
FuriString* item_time = furi_string_alloc(); FuriString* item_time = furi_string_alloc();

View File

@@ -3843,3 +3843,172 @@ C670A9AD6066
722538817225 722538817225
# 1k millenium hotels # 1k millenium hotels
132F641C948B 132F641C948B
############### from https://github.com/Stepzor11/NFC_keys ###############
CCCE24102003
49414556EF4D
1ABC15934F5A
0AD6B7E37183
C27F5C1A9C2B
7C9FB8474242
4663ACD2FFFF
FF75AFDA5A3C
4C44200BC9C5
3A4C47757B07
18AB07270506
A2CA48CA4C05
7B173A4E4976
8A55194F6587
4844426F6E69
6A0D531DA1A7
9B7C25052FC3
193DFE0FA18E
6CA761AB6CA7
4BB29463DC29
00B70875AF1D
20525276F443
3515AE068CAD
5A7D87876EA8
81CC25EBBB6A
9A677289564D
0A1B6C50E04E
F3A524B7A7B3
B133A4D48757
558AAD64EB5B
260480290483
1417E5671417
32F093536677
C9BE49675FE4
57A18BFEC381
AC37E76385F5
18E887D625B4
6686FADE5566
3D6F823FFFFF
427553754D47
9089B668FFFF
6C273F431564
34635A313344
353038383134
EDC317193709
75FAB77E2E5B
A1AB3A08712C
8DFACF11E778
6B3B7AF45777
45524DACC5E9
B1C4A8F7F6E3
6A6C80423226
537930363139
529CF51F05C5
374521A38BCC
EAB8066C7479
576DCFFF2F25
505209016A1F
186C59E6AFC9
8AC04C1A4E15
05597810D63D
453857395635
A1670589B2AF
552049EFF3F4
FCDDF7767C10
4149206E9BAE
54546255CDE9
C1F6C7B55F5E
3F3A534B7B7B
204C0D3DCD9A
5A2050DA7E3F
6B0454D5D3C3
2E0F00700000
0AD0956DF6EE
65B6C3200736
4F0E4AE8051A
8C187E78EE9C
544954CBB2C4
97D77FAE77D3
64CBADC7A313
4B92DF1BF25D
AB91BDA25F00
3A524B7A7B37
A58AB5619631
7F796F60FFFF
195DC63DB3A3
4752533E1965
FFF011223358
7213B13D02E0
76E450094393
202011F918A2
B793ADA6DB0C
F0A3C5182007
5A4920FD6F87
2900AAC52BC3
3C4ABB877EAF
80BB8436024C
48C8852D15F9
45450AC8DCA8
A5BB18152EF1
A514B797B373
C0AA2BBD27CD
9D56D83658AC
514B797B2F3A
0000FFFFFFFF
A777B233A4F4
F0FE56621A42
5044068C5183
494446555455
336E34CC2177
5AF445D2B87A
CDE668FDCDBA
1AF66F83F5BE
52B26C199862
593367486137
164EE10EFFFF
F4CE4AF888AE
3351916B5A77
E5519E1CC92B
04B787B2F3A5
EA0CA627FD06
2910AFE15C99
9D0D0A829F49
9AFEE1F65742
AE98BA1E6F2C
AB19BC885A29
E9AE90885C39
518108E061E2
066F5AF3CCEE
B95BFDEBA7E4
4B787B273A50
0F3A4D48757B
8627C10A7014
4E4F584D2105
707B11FC1481
DEDD7688BC38
81504133B13C
A71E80EA35E1
50D4C54FCDF5
2612C6DE84CA
FF9F11223358
738385948494
D23A31A4AAB9
9FAC23197904
AEF617B3D040
485242F22BE0
DDDAA35A9749
05412723F1B6
AEF617B3D004
7ADD3D735725
05C301C8795A
001122334455
B6803136F5AF
FE2A42E85CA8
43204334546F
16901CB400BC
307448829EBC
8FD6D76742DC
826576A1AB68
B3A4C47757B0
A6B3F6C8F1D4
702C1BF025DD
6BE9314930D8
777B1F3A4F4A
AA4DDA458EBB
CA80E51FA52B
C2A0105EB028
67B1B3A4E497

View File

@@ -0,0 +1,357 @@
#include "honeywell.h"
#include <lib/toolbox/manchester_decoder.h>
//Created by HTotoo 2023-10-30
//Got a lot of help from LiQuiDz.
//Protocol decoding help from: https://github.com/merbanan/rtl_433/blob/master/src/devices/honeywell.c
/*
64 bit packets, repeated multiple times per open/close event.
Protocol whitepaper: "DEFCON 22: Home Insecurity" by Logan Lamb.
Data layout:
PP PP C IIIII EE SS SS
- P: 16bit Preamble and sync bit (always ff fe)
- C: 4bit Channel
- I: 20bit Device serial number / or counter value
- E: 8bit Event, where 0x80 = Open/Close, 0x04 = Heartbeat / or id
- S: 16bit CRC
*/
#define TAG "SubGhzProtocolHoneywell"
uint16_t subghz_protocol_honeywell_crc16(
uint8_t const message[],
unsigned nBytes,
uint16_t polynomial,
uint16_t init) {
uint16_t remainder = init;
unsigned byte, bit;
for(byte = 0; byte < nBytes; ++byte) {
remainder ^= message[byte] << 8;
for(bit = 0; bit < 8; ++bit) {
if(remainder & 0x8000) {
remainder = (remainder << 1) ^ polynomial;
} else {
remainder = (remainder << 1);
}
}
}
return remainder;
}
void subghz_protocol_decoder_honeywell_free(void* context) {
furi_assert(context);
SubGhzProtocolDecoderHoneywell* instance = context;
free(instance);
}
void subghz_protocol_decoder_honeywell_reset(void* context) {
furi_assert(context);
SubGhzProtocolDecoderHoneywell* instance = context;
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
}
void subghz_protocol_decoder_honeywell_addbit(void* context, bool data) {
SubGhzProtocolDecoderHoneywell* instance = context;
instance->decoder.decode_data = (instance->decoder.decode_data << 1) | data;
instance->decoder.decode_count_bit++;
uint16_t preamble = (instance->decoder.decode_data >> 48) & 0xFFFF;
//can be multiple, since flipper can't read it well..
if(preamble == 0b0011111111111110 || preamble == 0b0111111111111110 ||
preamble == 0b1111111111111110) {
uint8_t datatocrc[4];
datatocrc[0] = (instance->decoder.decode_data >> 40) & 0xFFFF;
datatocrc[1] = (instance->decoder.decode_data >> 32) & 0xFFFF;
datatocrc[2] = (instance->decoder.decode_data >> 24) & 0xFFFF;
datatocrc[3] = (instance->decoder.decode_data >> 16) & 0xFFFF;
uint8_t channel = (instance->decoder.decode_data >> 44) & 0xF;
uint16_t crc_calc = 0;
if(channel == 0x2 || channel == 0x4 || channel == 0xA) {
// 2GIG brand
crc_calc = subghz_protocol_honeywell_crc16(datatocrc, 4, 0x8050, 0);
} else { // channel == 0x8
crc_calc = subghz_protocol_honeywell_crc16(datatocrc, 4, 0x8005, 0);
}
uint16_t crc = instance->decoder.decode_data & 0xFFFF;
if(crc == crc_calc) {
//the data is good. process it.
instance->generic.data = instance->decoder.decode_data;
instance->generic.data_count_bit =
instance->decoder
.decode_count_bit; //maybe set it to 64, and hack the first 2 bits to 1! will see if replay needs it
instance->generic.serial = (instance->decoder.decode_data >> 24) & 0xFFFFF;
instance->generic.btn = (instance->decoder.decode_data >> 16) &
0xFF; //not exactly button, but can contain btn data too.
if(instance->base.callback)
instance->base.callback(&instance->base, instance->base.context);
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
} else {
return;
}
}
}
void subghz_protocol_decoder_honeywell_feed(void* context, bool level, uint32_t duration) {
furi_assert(context);
SubGhzProtocolDecoderHoneywell* instance = context;
ManchesterEvent event = ManchesterEventReset;
if(!level) {
if(DURATION_DIFF(duration, subghz_protocol_honeywell_const.te_short) <
subghz_protocol_honeywell_const.te_delta) {
event = ManchesterEventShortLow;
} else if(
DURATION_DIFF(duration, subghz_protocol_honeywell_const.te_long) <
subghz_protocol_honeywell_const.te_delta * 2) {
event = ManchesterEventLongLow;
}
} else {
if(DURATION_DIFF(duration, subghz_protocol_honeywell_const.te_short) <
subghz_protocol_honeywell_const.te_delta) {
event = ManchesterEventShortHigh;
} else if(
DURATION_DIFF(duration, subghz_protocol_honeywell_const.te_long) <
subghz_protocol_honeywell_const.te_delta * 2) {
event = ManchesterEventLongHigh;
}
}
if(event != ManchesterEventReset) {
bool data;
bool data_ok = manchester_advance(
instance->manchester_saved_state, event, &instance->manchester_saved_state, &data);
if(data_ok) {
subghz_protocol_decoder_honeywell_addbit(instance, data);
}
} else {
instance->decoder.decode_data = 0;
instance->decoder.decode_count_bit = 0;
}
}
uint8_t subghz_protocol_decoder_honeywell_get_hash_data(void* context) {
furi_assert(context);
SubGhzProtocolDecoderHoneywell* instance = context;
return subghz_protocol_blocks_get_hash_data(
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
}
SubGhzProtocolStatus subghz_protocol_decoder_honeywell_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset) {
furi_assert(context);
SubGhzProtocolDecoderHoneywell* instance = context;
return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
}
SubGhzProtocolStatus
subghz_protocol_decoder_honeywell_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
SubGhzProtocolDecoderHoneywell* instance = context;
return subghz_block_generic_deserialize_check_count_bit(
&instance->generic,
flipper_format,
subghz_protocol_honeywell_const.min_count_bit_for_found);
}
void subghz_protocol_decoder_honeywell_get_string(void* context, FuriString* output) {
furi_assert(context);
SubGhzProtocolDecoderHoneywell* instance = context;
uint8_t channel = (instance->generic.data >> 44) & 0xF;
uint8_t contact = (instance->generic.btn & 0x80) >> 7;
uint8_t tamper = (instance->generic.btn & 0x40) >> 6;
uint8_t reed = (instance->generic.btn & 0x20) >> 5;
uint8_t alarm = (instance->generic.btn & 0x10) >> 4;
uint8_t battery_low = (instance->generic.btn & 0x08) >> 3;
uint8_t heartbeat = (instance->generic.btn & 0x04) >> 2;
furi_string_cat_printf(
output,
"%s\r\n%dbit "
"Sn:%07lu\r\nCh:%u Bat:%d Hb: %d\r\n"
"L1: %u, L2: %u, L3: %u, L4: %u\r\n",
instance->generic.protocol_name,
instance->generic.data_count_bit,
instance->generic.serial,
channel,
battery_low,
heartbeat,
contact,
reed,
alarm,
tamper);
}
void* subghz_protocol_decoder_honeywell_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
SubGhzProtocolDecoderHoneywell* instance = malloc(sizeof(SubGhzProtocolDecoderHoneywell));
instance->base.protocol = &subghz_protocol_honeywell;
instance->generic.protocol_name = instance->base.protocol->name;
return instance;
}
void* subghz_protocol_encoder_honeywell_alloc(SubGhzEnvironment* environment) {
UNUSED(environment);
SubGhzProtocolEncoderHoneywell* instance = malloc(sizeof(SubGhzProtocolEncoderHoneywell));
instance->base.protocol = &subghz_protocol_honeywell;
instance->generic.protocol_name = instance->base.protocol->name;
instance->encoder.repeat = 3;
instance->encoder.size_upload = 64 * 2 + 10;
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
instance->encoder.is_running = false;
return instance;
}
void subghz_protocol_encoder_honeywell_free(void* context) {
furi_assert(context);
SubGhzProtocolEncoderHoneywell* instance = context;
free(instance->encoder.upload);
free(instance);
}
static LevelDuration
subghz_protocol_encoder_honeywell_add_duration_to_upload(ManchesterEncoderResult result) {
LevelDuration data = {.duration = 0, .level = 0};
switch(result) {
case ManchesterEncoderResultShortLow:
data.duration = subghz_protocol_honeywell_const.te_short;
data.level = false;
break;
case ManchesterEncoderResultLongLow:
data.duration = subghz_protocol_honeywell_const.te_long;
data.level = false;
break;
case ManchesterEncoderResultLongHigh:
data.duration = subghz_protocol_honeywell_const.te_long;
data.level = true;
break;
case ManchesterEncoderResultShortHigh:
data.duration = subghz_protocol_honeywell_const.te_short;
data.level = true;
break;
default:
furi_crash("SubGhz: ManchesterEncoderResult is incorrect.");
break;
}
return level_duration_make(data.level, data.duration);
}
static void
subghz_protocol_encoder_honeywell_get_upload(SubGhzProtocolEncoderHoneywell* instance) {
furi_assert(instance);
size_t index = 0;
ManchesterEncoderState enc_state;
manchester_encoder_reset(&enc_state);
ManchesterEncoderResult result;
for(uint8_t i = 63; i > 0; i--) {
if(!manchester_encoder_advance(
&enc_state, bit_read(instance->generic.data, i - 1), &result)) {
instance->encoder.upload[index++] =
subghz_protocol_encoder_honeywell_add_duration_to_upload(result);
manchester_encoder_advance(
&enc_state, bit_read(instance->generic.data, i - 1), &result);
}
instance->encoder.upload[index++] =
subghz_protocol_encoder_honeywell_add_duration_to_upload(result);
}
instance->encoder.upload[index] = subghz_protocol_encoder_honeywell_add_duration_to_upload(
manchester_encoder_finish(&enc_state));
if(level_duration_get_level(instance->encoder.upload[index])) {
index++;
}
instance->encoder.size_upload = index;
}
SubGhzProtocolStatus
subghz_protocol_encoder_honeywell_deserialize(void* context, FlipperFormat* flipper_format) {
furi_assert(context);
SubGhzProtocolEncoderHoneywell* instance = context;
SubGhzProtocolStatus res = SubGhzProtocolStatusError;
do {
if(SubGhzProtocolStatusOk !=
subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
FURI_LOG_E(TAG, "Deserialize error");
break;
}
//optional parameter parameter
flipper_format_read_uint32(
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
subghz_protocol_encoder_honeywell_get_upload(instance);
if(!flipper_format_rewind(flipper_format)) {
FURI_LOG_E(TAG, "Rewind error");
break;
}
instance->encoder.is_running = true;
res = SubGhzProtocolStatusOk;
} while(false);
return res;
}
void subghz_protocol_encoder_honeywell_stop(void* context) {
SubGhzProtocolEncoderHoneywell* instance = context;
instance->encoder.is_running = false;
}
LevelDuration subghz_protocol_encoder_honeywell_yield(void* context) {
SubGhzProtocolEncoderHoneywell* instance = context;
if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
instance->encoder.is_running = false;
return level_duration_reset();
}
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
if(++instance->encoder.front == instance->encoder.size_upload) {
instance->encoder.repeat--;
instance->encoder.front = 0;
}
return ret;
}
const SubGhzProtocolDecoder subghz_protocol_honeywell_decoder = {
.alloc = subghz_protocol_decoder_honeywell_alloc,
.free = subghz_protocol_decoder_honeywell_free,
.feed = subghz_protocol_decoder_honeywell_feed,
.reset = subghz_protocol_decoder_honeywell_reset,
.get_hash_data = subghz_protocol_decoder_honeywell_get_hash_data,
.serialize = subghz_protocol_decoder_honeywell_serialize,
.deserialize = subghz_protocol_decoder_honeywell_deserialize,
.get_string = subghz_protocol_decoder_honeywell_get_string,
};
const SubGhzProtocolEncoder subghz_protocol_honeywell_encoder = {
.alloc = subghz_protocol_encoder_honeywell_alloc,
.free = subghz_protocol_encoder_honeywell_free,
.deserialize = subghz_protocol_encoder_honeywell_deserialize,
.stop = subghz_protocol_encoder_honeywell_stop,
.yield = subghz_protocol_encoder_honeywell_yield,
};
const SubGhzProtocol subghz_protocol_honeywell = {
.name = SUBGHZ_PROTOCOL_HONEYWELL_NAME,
.type = SubGhzProtocolTypeStatic,
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load |
SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
.encoder = &subghz_protocol_honeywell_encoder,
.decoder = &subghz_protocol_honeywell_decoder,
};

View File

@@ -0,0 +1,61 @@
#pragma once
#include <lib/subghz/protocols/base.h>
#include <lib/subghz/blocks/const.h>
#include <lib/subghz/blocks/decoder.h>
#include <lib/subghz/blocks/encoder.h>
#include "base.h"
#include "../blocks/generic.h"
#include <lib/subghz/blocks/math.h>
#include <lib/toolbox/manchester_decoder.h>
#include <lib/toolbox/manchester_encoder.h>
#define SUBGHZ_PROTOCOL_HONEYWELL_NAME "Honeywell Sec"
typedef struct SubGhzProtocolDecoderHoneywell SubGhzProtocolDecoderHoneywell;
typedef struct SubGhzProtocolEncoderHoneywell SubGhzProtocolEncoderHoneywell;
extern const SubGhzProtocolDecoder subghz_protocol_honeywell_decoder;
extern const SubGhzProtocolEncoder subghz_protocol_honeywell_encoder;
extern const SubGhzProtocol subghz_protocol_honeywell;
void* subghz_protocol_decoder_honeywell_alloc(SubGhzEnvironment* environment);
void subghz_protocol_decoder_honeywell_free(void* context);
void subghz_protocol_decoder_honeywell_reset(void* context);
void subghz_protocol_decoder_honeywell_feed(void* context, bool level, uint32_t duration);
uint8_t subghz_protocol_decoder_honeywell_get_hash_data(void* context);
SubGhzProtocolStatus subghz_protocol_decoder_honeywell_serialize(
void* context,
FlipperFormat* flipper_format,
SubGhzRadioPreset* preset);
SubGhzProtocolStatus
subghz_protocol_decoder_honeywell_deserialize(void* context, FlipperFormat* flipper_format);
void subghz_protocol_decoder_honeywell_get_string(void* context, FuriString* output);
static const SubGhzBlockConst subghz_protocol_honeywell_const = {
.te_long = 280,
.te_short = 143,
.te_delta = 51,
.min_count_bit_for_found = 62,
};
struct SubGhzProtocolDecoderHoneywell {
SubGhzProtocolDecoderBase base;
SubGhzBlockGeneric generic;
SubGhzBlockDecoder decoder;
ManchesterState manchester_saved_state;
};
struct SubGhzProtocolEncoderHoneywell {
SubGhzProtocolEncoderBase base;
SubGhzBlockGeneric generic;
SubGhzProtocolBlockEncoder encoder;
};

View File

@@ -10,9 +10,19 @@ static const SubGhzBlockConst pocsag_const = {
.te_short = 833, .te_short = 833,
.te_delta = 100, .te_delta = 100,
}; };
static const SubGhzBlockConst pocsag512_const = {
.te_short = 1950,
.te_long = 1950,
.te_delta = 120,
};
static const SubGhzBlockConst pocsag2400_const = {
.te_short = 410,
.te_long = 410,
.te_delta = 60,
};
// Minimal amount of sync bits (interleaving zeros and ones) // Minimal amount of sync bits (interleaving zeros and ones)
#define POCSAG_MIN_SYNC_BITS 32 #define POCSAG_MIN_SYNC_BITS 24
#define POCSAG_CW_BITS 32 #define POCSAG_CW_BITS 32
#define POCSAG_CW_MASK 0xFFFFFFFF #define POCSAG_CW_MASK 0xFFFFFFFF
#define POCSAG_FRAME_SYNC_CODE 0x7CD215D8 #define POCSAG_FRAME_SYNC_CODE 0x7CD215D8
@@ -45,6 +55,9 @@ struct SubGhzProtocolDecoderPocsag {
// Done messages, ready to be serialized/deserialized // Done messages, ready to be serialized/deserialized
FuriString* done_msg; FuriString* done_msg;
SubGhzBlockConst* pocsag_timing;
uint32_t version;
}; };
typedef struct SubGhzProtocolDecoderPocsag SubGhzProtocolDecoderPocsag; typedef struct SubGhzProtocolDecoderPocsag SubGhzProtocolDecoderPocsag;
@@ -64,6 +77,7 @@ void* subghz_protocol_decoder_pocsag_alloc(SubGhzEnvironment* environment) {
instance->generic.protocol_name = instance->base.protocol->name; instance->generic.protocol_name = instance->base.protocol->name;
instance->msg = furi_string_alloc(); instance->msg = furi_string_alloc();
instance->done_msg = furi_string_alloc(); instance->done_msg = furi_string_alloc();
instance->pocsag_timing = NULL; //not synced yet
if(instance->generic.result_msg == NULL) { if(instance->generic.result_msg == NULL) {
instance->generic.result_msg = furi_string_alloc(); instance->generic.result_msg = furi_string_alloc();
} }
@@ -179,6 +193,38 @@ void subghz_protocol_decoder_pocsag_feed(void* context, bool level, uint32_t dur
// reset state - waiting for 32 bits of interleaving 1s and 0s // reset state - waiting for 32 bits of interleaving 1s and 0s
if(instance->decoder.parser_step == PocsagDecoderStepReset) { if(instance->decoder.parser_step == PocsagDecoderStepReset) {
if(DURATION_DIFF(duration, pocsag_const.te_short) < pocsag_const.te_delta) { if(DURATION_DIFF(duration, pocsag_const.te_short) < pocsag_const.te_delta) {
if(instance->pocsag_timing != &pocsag_const) {
//timing changed, so reset before, and override
subghz_protocol_decoder_pocsag_reset(context);
instance->pocsag_timing = (SubGhzBlockConst*)&pocsag_const;
instance->version = 1200;
}
// POCSAG signals are inverted
subghz_protocol_blocks_add_bit(&instance->decoder, !level);
if(instance->decoder.decode_count_bit == POCSAG_MIN_SYNC_BITS) {
instance->decoder.parser_step = PocsagDecoderStepFoundSync;
}
} else if(DURATION_DIFF(duration, pocsag512_const.te_short) < pocsag512_const.te_delta) {
if(instance->pocsag_timing != &pocsag512_const) {
//timing changed, so reset before, and override
subghz_protocol_decoder_pocsag_reset(context);
instance->pocsag_timing = (SubGhzBlockConst*)&pocsag512_const;
instance->version = 512;
}
// POCSAG signals are inverted
subghz_protocol_blocks_add_bit(&instance->decoder, !level);
if(instance->decoder.decode_count_bit == POCSAG_MIN_SYNC_BITS) {
instance->decoder.parser_step = PocsagDecoderStepFoundSync;
}
} else if(DURATION_DIFF(duration, pocsag2400_const.te_short) < pocsag2400_const.te_delta) {
if(instance->pocsag_timing != &pocsag2400_const) {
//timing changed, so reset before, and override
subghz_protocol_decoder_pocsag_reset(context);
instance->pocsag_timing = (SubGhzBlockConst*)&pocsag2400_const;
instance->version = 2400;
}
// POCSAG signals are inverted // POCSAG signals are inverted
subghz_protocol_blocks_add_bit(&instance->decoder, !level); subghz_protocol_blocks_add_bit(&instance->decoder, !level);
@@ -191,12 +237,12 @@ void subghz_protocol_decoder_pocsag_feed(void* context, bool level, uint32_t dur
return; return;
} }
int bits_count = duration / pocsag_const.te_short; int bits_count = duration / instance->pocsag_timing->te_short;
uint32_t extra = duration - pocsag_const.te_short * bits_count; uint32_t extra = duration - instance->pocsag_timing->te_short * bits_count;
if(DURATION_DIFF(extra, pocsag_const.te_short) < pocsag_const.te_delta) if(DURATION_DIFF(extra, instance->pocsag_timing->te_short) < instance->pocsag_timing->te_delta)
bits_count++; bits_count++;
else if(extra > pocsag_const.te_delta) { else if(extra > instance->pocsag_timing->te_delta) {
// in non-reset state we faced the error signal - we reached the end of the packet, flush data // in non-reset state we faced the error signal - we reached the end of the packet, flush data
if(furi_string_size(instance->done_msg) > 0) { if(furi_string_size(instance->done_msg) > 0) {
if(instance->base.callback) if(instance->base.callback)
@@ -305,6 +351,11 @@ SubGhzProtocolStatus subghz_protocol_decoder_pocsag_serialize(
return SubGhzProtocolStatusError; return SubGhzProtocolStatusError;
} }
if(!flipper_format_write_uint32(flipper_format, "PocsagVer", &instance->version, 1)) {
FURI_LOG_E(TAG, "Error adding PocsagVer");
return SubGhzProtocolStatusError;
}
uint8_t* s = (uint8_t*)furi_string_get_cstr(instance->done_msg); uint8_t* s = (uint8_t*)furi_string_get_cstr(instance->done_msg);
if(!flipper_format_write_hex(flipper_format, "Msg", s, msg_len)) { if(!flipper_format_write_hex(flipper_format, "Msg", s, msg_len)) {
FURI_LOG_E(TAG, "Error adding Msg"); FURI_LOG_E(TAG, "Error adding Msg");
@@ -331,6 +382,9 @@ SubGhzProtocolStatus
FURI_LOG_E(TAG, "Missing MsgLen"); FURI_LOG_E(TAG, "Missing MsgLen");
break; break;
} }
//optional, so compatible backwards
instance->version = 1200;
flipper_format_read_uint32(flipper_format, "PocsagVer", &instance->version, 1);
buf = malloc(msg_len); buf = malloc(msg_len);
if(!flipper_format_read_hex(flipper_format, "Msg", buf, msg_len)) { if(!flipper_format_read_hex(flipper_format, "Msg", buf, msg_len)) {
@@ -349,7 +403,9 @@ SubGhzProtocolStatus
void subhz_protocol_decoder_pocsag_get_string(void* context, FuriString* output) { void subhz_protocol_decoder_pocsag_get_string(void* context, FuriString* output) {
furi_assert(context); furi_assert(context);
SubGhzProtocolDecoderPocsag* instance = context; SubGhzProtocolDecoderPocsag* instance = context;
furi_string_cat_printf(output, "%s\r\n", instance->generic.protocol_name); furi_string_cat_printf(
output, "%s %lu\r\n", instance->generic.protocol_name, instance->version);
furi_string_cat_printf(output, "Addr: %lu\r\n", instance->ric);
furi_string_cat(output, instance->done_msg); furi_string_cat(output, instance->done_msg);
} }

View File

@@ -31,6 +31,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = {
&subghz_protocol_bett, &subghz_protocol_bett,
&subghz_protocol_doitrand, &subghz_protocol_doitrand,
&subghz_protocol_phoenix_v2, &subghz_protocol_phoenix_v2,
&subghz_protocol_honeywell,
&subghz_protocol_honeywell_wdb, &subghz_protocol_honeywell_wdb,
&subghz_protocol_magellan, &subghz_protocol_magellan,
&subghz_protocol_intertechno_v3, &subghz_protocol_intertechno_v3,

View File

@@ -63,4 +63,5 @@
#include "auriol_ahfl.h" #include "auriol_ahfl.h"
#include "pocsag.h" #include "pocsag.h"
#include "schrader_gg4.h" #include "schrader_gg4.h"
#include "honeywell.h"
#include "bin_raw.h" #include "bin_raw.h"