Compare commits

...

3 Commits

Author SHA1 Message Date
D4rk$1d3
c6bec5ef4f Merge pull request #3 from LeeroysHub/main
All checks were successful
Build Dev Firmware / build (push) Successful in 6m25s
2026-03-21 23:02:27 -03:00
Leeroy
883d387246 Change BS to Checksum in Ford_V0 2026-03-22 08:49:31 +11:00
Leeroy
951f35c356 Remove unneeded BSMagic from Ford V0, we have proper BS calc now. 2026-03-22 07:29:32 +11:00

View File

@@ -55,7 +55,6 @@ typedef struct SubGhzProtocolDecoderFordV0 {
uint32_t serial; uint32_t serial;
uint8_t button; uint8_t button;
uint32_t count; uint32_t count;
uint8_t bs_magic;
} SubGhzProtocolDecoderFordV0; } SubGhzProtocolDecoderFordV0;
typedef struct SubGhzProtocolEncoderFordV0 { typedef struct SubGhzProtocolEncoderFordV0 {
SubGhzProtocolEncoderBase base; SubGhzProtocolEncoderBase base;
@@ -67,8 +66,7 @@ typedef struct SubGhzProtocolEncoderFordV0 {
uint32_t serial; uint32_t serial;
uint8_t button; uint8_t button;
uint32_t count; uint32_t count;
uint8_t bs; uint8_t checksum;
uint8_t bs_magic;
} SubGhzProtocolEncoderFordV0; } SubGhzProtocolEncoderFordV0;
typedef enum { typedef enum {
FordV0DecoderStepReset = 0, FordV0DecoderStepReset = 0,
@@ -88,14 +86,13 @@ static void decode_ford_v0(
uint16_t key2, uint16_t key2,
uint32_t* serial, uint32_t* serial,
uint8_t* button, uint8_t* button,
uint32_t* count, uint32_t* count);
uint8_t* bs_magic);
static void encode_ford_v0( static void encode_ford_v0(
uint8_t header_byte, uint8_t header_byte,
uint32_t serial, uint32_t serial,
uint8_t button, uint8_t button,
uint32_t count, uint32_t count,
uint8_t bs, uint8_t checksum,
uint64_t* key1); uint64_t* key1);
static bool ford_v0_process_data(SubGhzProtocolDecoderFordV0* instance); static bool ford_v0_process_data(SubGhzProtocolDecoderFordV0* instance);
@@ -122,7 +119,6 @@ const SubGhzProtocolEncoder subghz_protocol_ford_v0_encoder = {
.yield = subghz_protocol_encoder_ford_v0_yield, .yield = subghz_protocol_encoder_ford_v0_yield,
}; };
const SubGhzProtocol subghz_protocol_ford_v0 = { const SubGhzProtocol subghz_protocol_ford_v0 = {
.name = FORD_PROTOCOL_V0_NAME, .name = FORD_PROTOCOL_V0_NAME,
.type = SubGhzProtocolTypeDynamic, .type = SubGhzProtocolTypeDynamic,
@@ -133,19 +129,19 @@ const SubGhzProtocol subghz_protocol_ford_v0 = {
}; };
// ============================================================================= // =============================================================================
// BS CALCULATION // Checksum CALCULATION
// BS = (counter_low_byte + 0x6F + (button << 4)) & 0xFF // checksum = sum of bytes 1-7
// ============================================================================= // =============================================================================
static uint8_t ford_v0_calculate_bs_from_buf(uint8_t* buf) { static uint8_t ford_v0_calculate_checksum_from_buf(uint8_t* buf) {
// BS = sum of bytes 1..7 of the pre-XOR buffer // Checksum = sum of bytes 1..7 of the pre-XOR buffer
uint8_t checksum = 0; uint8_t checksum = 0;
for(int i = 1; i <= 7; i++) checksum += buf[i]; for(int i = 1; i <= 7; i++)
checksum += buf[i];
return checksum; return checksum;
} }
// ============================================================================= // =============================================================================
// CRC FUNCTIONS // CRC FUNCTIONS
// ============================================================================= // =============================================================================
static uint8_t ford_v0_popcount8(uint8_t x) { static uint8_t ford_v0_popcount8(uint8_t x) {
uint8_t count = 0; uint8_t count = 0;
while(x) { while(x) {
@@ -171,14 +167,14 @@ static uint8_t ford_v0_calculate_crc(uint8_t* buf) {
return crc; return crc;
} }
static uint8_t ford_v0_calculate_crc_for_tx(uint64_t key1, uint8_t bs) { static uint8_t ford_v0_calculate_crc_for_tx(uint64_t key1, uint8_t checksum) {
uint8_t buf[16] = {0}; uint8_t buf[16] = {0};
for(int i = 0; i < 8; ++i) { for(int i = 0; i < 8; ++i) {
buf[i] = (uint8_t)(key1 >> (56 - i * 8)); buf[i] = (uint8_t)(key1 >> (56 - i * 8));
} }
buf[8] = bs; buf[8] = checksum;
uint8_t crc = ford_v0_calculate_crc(buf); uint8_t crc = ford_v0_calculate_crc(buf);
return crc ^ 0x80; return crc ^ 0x80;
@@ -207,8 +203,7 @@ static void decode_ford_v0(
uint16_t key2, uint16_t key2,
uint32_t* serial, uint32_t* serial,
uint8_t* button, uint8_t* button,
uint32_t* count, uint32_t* count) {
uint8_t* bs_magic) {
uint8_t buf[13] = {0}; uint8_t buf[13] = {0};
for(int i = 0; i < 8; ++i) { for(int i = 0; i < 8; ++i) {
@@ -219,7 +214,7 @@ static void decode_ford_v0(
buf[9] = (uint8_t)(key2 & 0xFF); buf[9] = (uint8_t)(key2 & 0xFF);
uint8_t tmp = buf[8]; uint8_t tmp = buf[8];
uint8_t bs = tmp; //uint8_t checksum = tmp; //KEPT FOR CLARITY
uint8_t parity = 0; uint8_t parity = 0;
uint8_t parity_any = (tmp != 0); uint8_t parity_any = (tmp != 0);
while(tmp) { while(tmp) {
@@ -261,9 +256,6 @@ static void decode_ford_v0(
*button = (buf[5] >> 4) & 0x0F; *button = (buf[5] >> 4) & 0x0F;
*count = ((buf[5] & 0x0F) << 16) | (buf[6] << 8) | buf[7]; *count = ((buf[5] & 0x0F) << 16) | (buf[6] << 8) | buf[7];
// BS is checksum of bytes 1..7 (pre-XOR), stored for verification only
*bs_magic = bs; // kept for compatibility, not used in encode
} }
// ============================================================================= // =============================================================================
@@ -274,7 +266,7 @@ static void encode_ford_v0(
uint32_t serial, uint32_t serial,
uint8_t button, uint8_t button,
uint32_t count, uint32_t count,
uint8_t bs, uint8_t checksum,
uint64_t* key1) { uint64_t* key1) {
if(!key1) { if(!key1) {
FURI_LOG_E(TAG, "encode_ford_v0: NULL key1 pointer"); FURI_LOG_E(TAG, "encode_ford_v0: NULL key1 pointer");
@@ -301,19 +293,19 @@ static void encode_ford_v0(
buf[6] = pre_xor_6; buf[6] = pre_xor_6;
buf[7] = pre_xor_7; buf[7] = pre_xor_7;
// BS = checksum of bytes 1..7 before XOR //checksum = checksum of bytes 1..7 before XOR
bs = ford_v0_calculate_bs_from_buf(buf); checksum = ford_v0_calculate_checksum_from_buf(buf);
uint8_t post_xor_6 = (count_mid & 0xAA) | (count_low & 0x55); uint8_t post_xor_6 = (count_mid & 0xAA) | (count_low & 0x55);
uint8_t post_xor_7 = (count_low & 0xAA) | (count_mid & 0x55); uint8_t post_xor_7 = (count_low & 0xAA) | (count_mid & 0x55);
uint8_t parity = 0; uint8_t parity = 0;
uint8_t tmp = bs; uint8_t tmp = checksum;
while(tmp) { while(tmp) {
parity ^= (tmp & 1); parity ^= (tmp & 1);
tmp >>= 1; tmp >>= 1;
} }
bool parity_bit = (bs != 0) ? (parity != 0) : false; bool parity_bit = (checksum != 0) ? (parity != 0) : false;
if(parity_bit) { if(parity_bit) {
uint8_t xor_byte = post_xor_7; uint8_t xor_byte = post_xor_7;
@@ -342,11 +334,11 @@ static void encode_ford_v0(
FURI_LOG_I( FURI_LOG_I(
TAG, TAG,
"Encode: Sn=%08lX Btn=%d Cnt=%05lX BS=%02X", "Encode: Sn=%08lX Btn=%d Cnt=%05lX Checksum=%02X",
(unsigned long)serial, (unsigned long)serial,
button, button,
(unsigned long)count, (unsigned long)count,
bs); checksum);
FURI_LOG_I( FURI_LOG_I(
TAG, TAG,
"Encode key1: %08lX%08lX", "Encode key1: %08lX%08lX",
@@ -361,10 +353,10 @@ static void encode_ford_v0(
static uint8_t subghz_protocol_ford_v0_get_btn_code(void) { static uint8_t subghz_protocol_ford_v0_get_btn_code(void) {
uint8_t custom_btn = subghz_custom_btn_get(); uint8_t custom_btn = subghz_custom_btn_get();
uint8_t original_btn = subghz_custom_btn_get_original(); uint8_t original_btn = subghz_custom_btn_get_original();
if(custom_btn == SUBGHZ_CUSTOM_BTN_OK) return original_btn; if(custom_btn == SUBGHZ_CUSTOM_BTN_OK) return original_btn;
if(custom_btn == SUBGHZ_CUSTOM_BTN_UP) return 0x01; // Lock if(custom_btn == SUBGHZ_CUSTOM_BTN_UP) return 0x01; // Lock
if(custom_btn == SUBGHZ_CUSTOM_BTN_DOWN) return 0x02; // Unlock if(custom_btn == SUBGHZ_CUSTOM_BTN_DOWN) return 0x02; // Unlock
if(custom_btn == SUBGHZ_CUSTOM_BTN_LEFT) return 0x04; // Boot/Trunk if(custom_btn == SUBGHZ_CUSTOM_BTN_LEFT) return 0x04; // Boot/Trunk
if(custom_btn == SUBGHZ_CUSTOM_BTN_RIGHT) return 0x04; // Boot/Trunk if(custom_btn == SUBGHZ_CUSTOM_BTN_RIGHT) return 0x04; // Boot/Trunk
return original_btn; return original_btn;
} }
@@ -387,8 +379,7 @@ void* subghz_protocol_encoder_ford_v0_alloc(SubGhzEnvironment* environment) {
instance->serial = 0; instance->serial = 0;
instance->button = 0; instance->button = 0;
instance->count = 0; instance->count = 0;
instance->bs = 0; instance->checksum = 0;
instance->bs_magic = 0;
FURI_LOG_I(TAG, "Encoder allocated"); FURI_LOG_I(TAG, "Encoder allocated");
return instance; return instance;
@@ -586,14 +577,6 @@ SubGhzProtocolStatus
break; break;
} }
instance->generic.cnt = instance->count; instance->generic.cnt = instance->count;
flipper_format_rewind(flipper_format);
uint32_t bs_magic_temp = 0;
if(!flipper_format_read_uint32(flipper_format, "BSMagic", &bs_magic_temp, 1))
instance->bs_magic = 0x6F;
else
instance->bs_magic = (uint8_t)bs_magic_temp;
instance->count = (instance->count + 1) & 0xFFFFF; instance->count = (instance->count + 1) & 0xFFFFF;
instance->generic.cnt = instance->count; instance->generic.cnt = instance->count;
@@ -604,27 +587,33 @@ SubGhzProtocolStatus
instance->button = subghz_protocol_ford_v0_get_btn_code(); instance->button = subghz_protocol_ford_v0_get_btn_code();
// BS is calculated inside encode_ford_v0 from buf[1..7] // Checksum is calculated inside encode_ford_v0 from buf[1..7]
instance->bs = 0; // will be set by encode_ford_v0 instance->checksum = 0; // will be set by encode_ford_v0
encode_ford_v0( encode_ford_v0(
header_byte, header_byte,
instance->serial, instance->serial,
instance->button, instance->button,
instance->count, instance->count,
instance->bs, instance->checksum,
&instance->key1); &instance->key1);
instance->generic.data = instance->key1; instance->generic.data = instance->key1;
instance->generic.data_count_bit = 64; instance->generic.data_count_bit = 64;
uint8_t calculated_crc = ford_v0_calculate_crc_for_tx(instance->key1, instance->bs); uint8_t calculated_crc = ford_v0_calculate_crc_for_tx(instance->key1, instance->checksum);
instance->key2 = ((uint16_t)instance->bs << 8) | calculated_crc; instance->key2 = ((uint16_t)instance->checksum << 8) | calculated_crc;
FURI_LOG_I(TAG, "Encoded: Sn=%08lX Btn=%02X Cnt=%05lX BS=%02X CRC=%02X key1=%08lX%08lX", FURI_LOG_I(
(unsigned long)instance->serial, instance->button, TAG,
(unsigned long)instance->count, instance->bs, calculated_crc, "Encoded: Sn=%08lX Btn=%02X Cnt=%05lX Checksum=%02X CRC=%02X key1=%08lX%08lX",
(unsigned long)(instance->key1 >> 32), (unsigned long)(instance->key1 & 0xFFFFFFFF)); (unsigned long)instance->serial,
instance->button,
(unsigned long)instance->count,
instance->checksum,
calculated_crc,
(unsigned long)(instance->key1 >> 32),
(unsigned long)(instance->key1 & 0xFFFFFFFF));
flipper_format_rewind(flipper_format); flipper_format_rewind(flipper_format);
if(!flipper_format_read_uint32( if(!flipper_format_read_uint32(
@@ -649,8 +638,8 @@ SubGhzProtocolStatus
bool cnt_wr = flipper_format_insert_or_update_uint32(flipper_format, "Cnt", &temp, 1); bool cnt_wr = flipper_format_insert_or_update_uint32(flipper_format, "Cnt", &temp, 1);
temp = calculated_crc; temp = calculated_crc;
flipper_format_insert_or_update_uint32(flipper_format, "CRC", &temp, 1); flipper_format_insert_or_update_uint32(flipper_format, "CRC", &temp, 1);
temp = instance->bs; temp = instance->checksum;
flipper_format_insert_or_update_uint32(flipper_format, "BS", &temp, 1); flipper_format_insert_or_update_uint32(flipper_format, "Checksum", &temp, 1);
FURI_LOG_I(TAG, "File updated: Key ok=%d Cnt ok=%d", key_wr, cnt_wr); FURI_LOG_I(TAG, "File updated: Key ok=%d Cnt ok=%d", key_wr, cnt_wr);
@@ -715,12 +704,7 @@ static bool ford_v0_process_data(SubGhzProtocolDecoderFordV0* instance) {
uint16_t key2 = ~key2_raw; uint16_t key2 = ~key2_raw;
decode_ford_v0( decode_ford_v0(
instance->key1, instance->key1, key2, &instance->serial, &instance->button, &instance->count);
key2,
&instance->serial,
&instance->button,
&instance->count,
&instance->bs_magic);
instance->key2 = key2; instance->key2 = key2;
return true; return true;
@@ -759,7 +743,6 @@ void subghz_protocol_decoder_ford_v0_reset(void* context) {
instance->serial = 0; instance->serial = 0;
instance->button = 0; instance->button = 0;
instance->count = 0; instance->count = 0;
instance->bs_magic = 0;
} }
void subghz_protocol_decoder_ford_v0_feed(void* context, bool level, uint32_t duration) { void subghz_protocol_decoder_ford_v0_feed(void* context, bool level, uint32_t duration) {
@@ -884,7 +867,7 @@ SubGhzProtocolStatus subghz_protocol_decoder_ford_v0_serialize(
if(ret == SubGhzProtocolStatusOk) { if(ret == SubGhzProtocolStatusOk) {
uint32_t temp = (instance->key2 >> 8) & 0xFF; uint32_t temp = (instance->key2 >> 8) & 0xFF;
flipper_format_write_uint32(flipper_format, "BS", &temp, 1); flipper_format_write_uint32(flipper_format, "Checksum", &temp, 1);
temp = instance->key2 & 0xFF; temp = instance->key2 & 0xFF;
flipper_format_write_uint32(flipper_format, "CRC", &temp, 1); flipper_format_write_uint32(flipper_format, "CRC", &temp, 1);
@@ -895,9 +878,6 @@ SubGhzProtocolStatus subghz_protocol_decoder_ford_v0_serialize(
flipper_format_write_uint32(flipper_format, "Btn", &temp, 1); flipper_format_write_uint32(flipper_format, "Btn", &temp, 1);
flipper_format_write_uint32(flipper_format, "Cnt", &instance->count, 1); flipper_format_write_uint32(flipper_format, "Cnt", &instance->count, 1);
temp = (uint32_t)instance->bs_magic;
flipper_format_write_uint32(flipper_format, "BSMagic", &temp, 1);
} }
return ret; return ret;
@@ -911,7 +891,9 @@ SubGhzProtocolStatus
SubGhzProtocolStatus ret = subghz_block_generic_deserialize_check_count_bit( SubGhzProtocolStatus ret = subghz_block_generic_deserialize_check_count_bit(
&instance->generic, flipper_format, subghz_protocol_ford_v0_const.min_count_bit_for_found); &instance->generic, flipper_format, subghz_protocol_ford_v0_const.min_count_bit_for_found);
FURI_LOG_I(TAG, "Decoder deserialize: generic_ret=%d generic.data=%08lX%08lX", FURI_LOG_I(
TAG,
"Decoder deserialize: generic_ret=%d generic.data=%08lX%08lX",
ret, ret,
(unsigned long)(instance->generic.data >> 32), (unsigned long)(instance->generic.data >> 32),
(unsigned long)(instance->generic.data & 0xFFFFFFFF)); (unsigned long)(instance->generic.data & 0xFFFFFFFF));
@@ -921,12 +903,17 @@ SubGhzProtocolStatus
flipper_format_rewind(flipper_format); flipper_format_rewind(flipper_format);
uint32_t bs_temp = 0; uint32_t checksum_temp = 0;
uint32_t crc_temp = 0; uint32_t crc_temp = 0;
flipper_format_read_uint32(flipper_format, "BS", &bs_temp, 1); flipper_format_read_uint32(flipper_format, "Checksum", &checksum_temp, 1);
flipper_format_read_uint32(flipper_format, "CRC", &crc_temp, 1); flipper_format_read_uint32(flipper_format, "CRC", &crc_temp, 1);
instance->key2 = ((bs_temp & 0xFF) << 8) | (crc_temp & 0xFF); instance->key2 = ((checksum_temp & 0xFF) << 8) | (crc_temp & 0xFF);
FURI_LOG_I(TAG, "Decoder deserialize: BS=0x%02lX CRC=0x%02lX key2=0x%04X", bs_temp, crc_temp, instance->key2); FURI_LOG_I(
TAG,
"Decoder deserialize: Checksum=0x%02lX CRC=0x%02lX key2=0x%04X",
checksum_temp,
crc_temp,
instance->key2);
flipper_format_read_uint32(flipper_format, "Serial", &instance->serial, 1); flipper_format_read_uint32(flipper_format, "Serial", &instance->serial, 1);
instance->generic.serial = instance->serial; instance->generic.serial = instance->serial;
@@ -939,18 +926,16 @@ SubGhzProtocolStatus
flipper_format_read_uint32(flipper_format, "Cnt", &instance->count, 1); flipper_format_read_uint32(flipper_format, "Cnt", &instance->count, 1);
instance->generic.cnt = instance->count; instance->generic.cnt = instance->count;
FURI_LOG_I(TAG, "Decoder deserialize: Sn=0x%08lX Btn=0x%02X Cnt=0x%05lX", FURI_LOG_I(
TAG,
"Decoder deserialize: Sn=0x%08lX Btn=0x%02X Cnt=0x%05lX",
(unsigned long)instance->serial, (unsigned long)instance->serial,
instance->button, instance->button,
(unsigned long)instance->count); (unsigned long)instance->count);
uint32_t bs_magic_temp = 0; FURI_LOG_I(
if(flipper_format_read_uint32(flipper_format, "BSMagic", &bs_magic_temp, 1)) TAG,
instance->bs_magic = bs_magic_temp; "Decoder deserialize: key1=%08lX%08lX",
else
instance->bs_magic = 0x6F;
FURI_LOG_I(TAG, "Decoder deserialize: BSMagic=0x%02X key1=%08lX%08lX",
instance->bs_magic,
(unsigned long)(instance->key1 >> 32), (unsigned long)(instance->key1 >> 32),
(unsigned long)(instance->key1 & 0xFFFFFFFF)); (unsigned long)(instance->key1 & 0xFFFFFFFF));
} }
@@ -998,6 +983,5 @@ void subghz_protocol_decoder_ford_v0_get_string(void* context, FuriString* outpu
(unsigned long)instance->count, (unsigned long)instance->count,
(unsigned int)display_btn, (unsigned int)display_btn,
button_name, button_name,
crc_ok ? "OK" : "BAD" crc_ok ? "OK" : "BAD");
);
} }