Skip to content

Commit bd9eebf

Browse files
Merge pull request #57 from RocketGod-git/Ford-V0-CRC-(ENCODER)
Add CRC to encoder
2 parents f5e7c73 + 0d04383 commit bd9eebf

1 file changed

Lines changed: 41 additions & 104 deletions

File tree

protocols/ford_v0.c

Lines changed: 41 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@ static const SubGhzBlockConst subghz_protocol_ford_v0_const = {
1515

1616
// Ford V0 CRC Matrix (8x8 bytes) - extracted from firmware
1717
static const uint8_t ford_v0_crc_matrix[64] = {
18-
0xDA, 0xB5, 0x55, 0x6A, 0xAA, 0xAA, 0xAA, 0xD5, // Row 0
19-
0xB6, 0x6C, 0xCC, 0xD9, 0x99, 0x99, 0x99, 0xB3, // Row 1
20-
0x71, 0xE3, 0xC3, 0xC7, 0x87, 0x87, 0x87, 0x8F, // Row 2
21-
0x0F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0x7F, 0x80, // Row 3
22-
0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0x80, // Row 4
23-
0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0x80, // Row 5
24-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, // Row 6
25-
0x23, 0x12, 0x94, 0x84, 0x35, 0xF4, 0x55, 0x84, // Row 7
18+
0xDA, 0xB5, 0x55, 0x6A, 0xAA, 0xAA, 0xAA, 0xD5, // Row 0
19+
0xB6, 0x6C, 0xCC, 0xD9, 0x99, 0x99, 0x99, 0xB3, // Row 1
20+
0x71, 0xE3, 0xC3, 0xC7, 0x87, 0x87, 0x87, 0x8F, // Row 2
21+
0x0F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0x7F, 0x80, // Row 3
22+
0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0x80, // Row 4
23+
0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0x80, // Row 5
24+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, // Row 6
25+
0x23, 0x12, 0x94, 0x84, 0x35, 0xF4, 0x55, 0x84, // Row 7
2626
};
2727

2828
// ============================================================================
29-
// CRC FUNCTIONS (for decoder verification)
29+
// CRC FUNCTIONS
3030
// ============================================================================
3131

3232
static uint8_t ford_v0_popcount8(uint8_t x) {
@@ -42,18 +42,6 @@ static uint8_t ford_v0_popcount8(uint8_t x) {
4242
static uint8_t ford_v0_calculate_crc(uint8_t* buf) {
4343
uint8_t crc = 0;
4444

45-
FURI_LOG_D(
46-
TAG,
47-
"CRC calc input: buf[1-8] = %02X %02X %02X %02X %02X %02X %02X %02X",
48-
buf[1],
49-
buf[2],
50-
buf[3],
51-
buf[4],
52-
buf[5],
53-
buf[6],
54-
buf[7],
55-
buf[8]);
56-
5745
for(int row = 0; row < 8; row++) {
5846
uint8_t xor_sum = 0;
5947
for(int col = 0; col < 8; col++) {
@@ -63,23 +51,29 @@ static uint8_t ford_v0_calculate_crc(uint8_t* buf) {
6351
if(parity) {
6452
crc |= (1 << row);
6553
}
66-
FURI_LOG_D(
67-
TAG,
68-
"CRC row %d: xor_sum=0x%02X popcount=%d parity=%d crc_so_far=0x%02X",
69-
row,
70-
xor_sum,
71-
ford_v0_popcount8(xor_sum),
72-
parity,
73-
crc);
7454
}
7555

76-
// XOR with 0x80 - Ford appears to invert bit 7
77-
crc ^= 0x80;
78-
79-
FURI_LOG_D(TAG, "CRC calculated: 0x%02X", crc);
8056
return crc;
8157
}
8258

59+
// Calculate CRC for encoding: returns the value to transmit
60+
static uint8_t ford_v0_calculate_crc_for_tx(uint64_t key1, uint8_t bs) {
61+
uint8_t buf[16] = {0};
62+
63+
// Extract bytes from key1 into buf[0..7]
64+
for(int i = 0; i < 8; ++i) {
65+
buf[i] = (uint8_t)(key1 >> (56 - i * 8));
66+
}
67+
68+
// BS goes into buf[8]
69+
buf[8] = bs;
70+
71+
// Calculate CRC and XOR with 0x80 for transmission
72+
uint8_t crc = ford_v0_calculate_crc(buf);
73+
return crc ^ 0x80;
74+
}
75+
76+
// Verify received CRC
8377
static bool ford_v0_verify_crc(uint64_t key1, uint16_t key2) {
8478
uint8_t buf[16] = {0};
8579

@@ -91,34 +85,9 @@ static bool ford_v0_verify_crc(uint64_t key1, uint16_t key2) {
9185
// BS is high byte of key2, goes into buf[8]
9286
buf[8] = (uint8_t)(key2 >> 8);
9387

94-
FURI_LOG_I(
95-
TAG,
96-
"CRC verify: key1=0x%08lX%08lX key2=0x%04X",
97-
(uint32_t)(key1 >> 32),
98-
(uint32_t)(key1 & 0xFFFFFFFF),
99-
key2);
100-
FURI_LOG_I(
101-
TAG,
102-
"CRC verify: buf[0-8] = %02X %02X %02X %02X %02X %02X %02X %02X %02X",
103-
buf[0],
104-
buf[1],
105-
buf[2],
106-
buf[3],
107-
buf[4],
108-
buf[5],
109-
buf[6],
110-
buf[7],
111-
buf[8]);
112-
11388
uint8_t calculated_crc = ford_v0_calculate_crc(buf);
114-
uint8_t received_crc = (uint8_t)(key2 & 0xFF);
115-
116-
FURI_LOG_I(
117-
TAG,
118-
"CRC compare: calculated=0x%02X received=0x%02X match=%s",
119-
calculated_crc,
120-
received_crc,
121-
(calculated_crc == received_crc) ? "YES" : "NO");
89+
// Received CRC has bit 7 inverted
90+
uint8_t received_crc = (uint8_t)(key2 & 0xFF) ^ 0x80;
12291

12392
return (calculated_crc == received_crc);
12493
}
@@ -437,19 +406,23 @@ SubGhzProtocolStatus
437406
}
438407
instance->generic.cnt = instance->count;
439408

409+
// Read BS from file
440410
uint32_t bs_temp = 0;
441411
flipper_format_read_uint32(flipper_format, "BS", &bs_temp, 1);
412+
uint8_t bs = (uint8_t)(bs_temp & 0xFF);
442413

443-
uint32_t crc_temp = 0;
444-
flipper_format_read_uint32(flipper_format, "CRC", &crc_temp, 1);
414+
// Calculate CRC from key1 and BS
415+
uint8_t calculated_crc = ford_v0_calculate_crc_for_tx(instance->key1, bs);
416+
417+
// Build key2 from BS and calculated CRC
418+
instance->key2 = ((uint16_t)bs << 8) | calculated_crc;
445419

446-
instance->key2 = ((bs_temp & 0xFF) << 8) | (crc_temp & 0xFF);
447420
FURI_LOG_I(
448421
TAG,
449-
"Reconstructed key2: 0x%04X (BS=0x%02X, CRC=0x%02X)",
422+
"Encoder key2: 0x%04X (BS=0x%02X, CRC=0x%02X calculated)",
450423
instance->key2,
451-
(uint8_t)bs_temp,
452-
(uint8_t)crc_temp);
424+
bs,
425+
calculated_crc);
453426

454427
if(!flipper_format_read_uint32(
455428
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1)) {
@@ -581,42 +554,15 @@ static bool ford_v0_process_data(SubGhzProtocolDecoderFordV0* instance) {
581554
instance->key1 = ~combined;
582555
instance->data_low = 0;
583556
instance->data_high = 0;
584-
FURI_LOG_I(
585-
TAG,
586-
"Got 64 bits, key1=0x%08lX%08lX",
587-
(uint32_t)(instance->key1 >> 32),
588-
(uint32_t)(instance->key1 & 0xFFFFFFFF));
589557
return false;
590558
}
591559

592560
if(instance->bit_count == 80) {
593561
uint16_t key2_raw = (uint16_t)(instance->data_low & 0xFFFF);
594562
uint16_t key2 = ~key2_raw;
595-
596-
FURI_LOG_I(TAG, "Got 80 bits, key2_raw=0x%04X key2=0x%04X", key2_raw, key2);
597-
598-
// Verify CRC
599-
bool crc_ok = ford_v0_verify_crc(instance->key1, key2);
600-
601-
FURI_LOG_I(
602-
TAG,
603-
"Received: key1=0x%08lX%08lX key2=0x%04X CRC=%s",
604-
(uint32_t)(instance->key1 >> 32),
605-
(uint32_t)(instance->key1 & 0xFFFFFFFF),
606-
key2,
607-
crc_ok ? "OK" : "BAD");
608-
609563
decode_ford_v0(
610564
instance->key1, key2, &instance->serial, &instance->button, &instance->count);
611565
instance->key2 = key2;
612-
613-
FURI_LOG_I(
614-
TAG,
615-
"Decoded: Sn=0x%08lX Btn=%d Cnt=0x%05lX",
616-
instance->serial,
617-
instance->button,
618-
instance->count);
619-
620566
return true;
621567
}
622568

@@ -819,7 +765,7 @@ SubGhzProtocolStatus
819765
if(ret == SubGhzProtocolStatusOk) {
820766
instance->key1 = instance->generic.data;
821767

822-
// Rewind and read all custom fields
768+
// Rewind and read custom fields
823769
flipper_format_rewind(flipper_format);
824770

825771
uint32_t bs_temp = 0;
@@ -828,15 +774,6 @@ SubGhzProtocolStatus
828774
flipper_format_read_uint32(flipper_format, "CRC", &crc_temp, 1);
829775
instance->key2 = ((bs_temp & 0xFF) << 8) | (crc_temp & 0xFF);
830776

831-
FURI_LOG_I(
832-
TAG,
833-
"Deserialize: key1=0x%08lX%08lX key2=0x%04X (BS=%02X CRC=%02X)",
834-
(uint32_t)(instance->key1 >> 32),
835-
(uint32_t)(instance->key1 & 0xFFFFFFFF),
836-
instance->key2,
837-
(uint8_t)bs_temp,
838-
(uint8_t)crc_temp);
839-
840777
flipper_format_read_uint32(flipper_format, "Serial", &instance->serial, 1);
841778
instance->generic.serial = instance->serial;
842779

@@ -888,4 +825,4 @@ void subghz_protocol_decoder_ford_v0_get_string(void* context, FuriString* outpu
888825
instance->count,
889826
(instance->key2 >> 8) & 0xFF,
890827
instance->key2 & 0xFF);
891-
}
828+
}

0 commit comments

Comments
 (0)