mirror of
https://github.com/D4C1-Labs/Flipper-ARF.git
synced 2026-04-18 04:35:45 +00:00
Compare commits
6 Commits
dev-0ebf26
...
dev-6a348d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a348dd304 | ||
|
|
32a96e580d | ||
|
|
54f03a39c2 | ||
|
|
a55189e2a4 | ||
|
|
14d10c0794 | ||
|
|
27818ccb1f |
@@ -44,7 +44,7 @@ const SubGhzProtocol* const subghz_protocol_registry_items[] = {
|
||||
//&subghz_protocol_honeywell,
|
||||
//&subghz_protocol_legrand,
|
||||
&subghz_protocol_dickert_mahs,
|
||||
//&subghz_protocol_gangqi,
|
||||
&subghz_protocol_gangqi,
|
||||
&subghz_protocol_marantec24,
|
||||
//&subghz_protocol_hollarm,
|
||||
&subghz_protocol_hay21,
|
||||
@@ -76,7 +76,7 @@ const SubGhzProtocol* const subghz_protocol_registry_items[] = {
|
||||
&subghz_protocol_star_line,
|
||||
&subghz_protocol_scher_khan,
|
||||
&subghz_protocol_sheriff_cfm,
|
||||
&subghz_protocol_honda,
|
||||
// until fix &subghz_protocol_honda,
|
||||
&subghz_protocol_chrysler,
|
||||
};
|
||||
|
||||
|
||||
@@ -125,6 +125,10 @@ struct SubGhzProtocolDecoderPSA {
|
||||
|
||||
uint32_t last_key1_low;
|
||||
uint32_t last_key1_high;
|
||||
|
||||
uint32_t te_sum;
|
||||
uint16_t te_count;
|
||||
uint32_t te_detected;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolEncoderPSA {
|
||||
@@ -670,6 +674,9 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati
|
||||
instance->pattern_counter = 0;
|
||||
instance->decode_count_bit = 0;
|
||||
instance->mode_serialize = 0;
|
||||
instance->te_sum = duration;
|
||||
instance->te_count = 1;
|
||||
instance->te_detected = 0;
|
||||
instance->prev_duration = duration;
|
||||
manchester_advance(instance->manchester_state, ManchesterEventReset,
|
||||
&instance->manchester_state, NULL);
|
||||
@@ -935,39 +942,35 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati
|
||||
return;
|
||||
}
|
||||
|
||||
if(duration < PSA_TE_SHORT_125) {
|
||||
tolerance = PSA_TE_SHORT_125 - duration;
|
||||
if(tolerance < PSA_TOLERANCE_50) {
|
||||
uint32_t prev_diff = psa_abs_diff(prev_dur, PSA_TE_SHORT_125);
|
||||
if(prev_diff <= PSA_TOLERANCE_49) {
|
||||
instance->pattern_counter++;
|
||||
} else {
|
||||
instance->pattern_counter = 0;
|
||||
}
|
||||
instance->prev_duration = duration;
|
||||
return;
|
||||
// Adaptive AM preamble: accept 76-174us, average to detect actual TE
|
||||
if(duration >= 76 && duration <= 174) {
|
||||
if(prev_dur >= 76 && prev_dur <= 174) {
|
||||
instance->pattern_counter++;
|
||||
instance->te_sum += duration;
|
||||
instance->te_count++;
|
||||
} else {
|
||||
instance->pattern_counter = 0;
|
||||
instance->te_sum = duration;
|
||||
instance->te_count = 1;
|
||||
}
|
||||
instance->prev_duration = duration;
|
||||
return;
|
||||
} else {
|
||||
tolerance = duration - PSA_TE_SHORT_125;
|
||||
if(tolerance < PSA_TOLERANCE_50) {
|
||||
uint32_t prev_diff = psa_abs_diff(prev_dur, PSA_TE_SHORT_125);
|
||||
if(prev_diff <= PSA_TOLERANCE_49) {
|
||||
instance->pattern_counter++;
|
||||
} else {
|
||||
instance->pattern_counter = 0;
|
||||
}
|
||||
instance->prev_duration = duration;
|
||||
return;
|
||||
} else if(duration >= PSA_TE_LONG_250 && duration < 0x12c) {
|
||||
if(instance->pattern_counter > PSA_PATTERN_THRESHOLD_2) {
|
||||
new_state = PSADecoderState4;
|
||||
instance->decode_data_low = 0;
|
||||
instance->decode_data_high = 0;
|
||||
instance->decode_count_bit = 0;
|
||||
manchester_advance(instance->manchester_state, ManchesterEventReset,
|
||||
&instance->manchester_state, NULL);
|
||||
instance->state = new_state;
|
||||
}
|
||||
// Check if this is the preamble-to-data transition (2x detected TE)
|
||||
uint32_t te_avg = (instance->te_count > 0) ?
|
||||
(instance->te_sum / instance->te_count) : PSA_TE_SHORT_125;
|
||||
uint32_t te_long_expected = te_avg * 2;
|
||||
uint32_t long_diff = psa_abs_diff(duration, te_long_expected);
|
||||
|
||||
if(long_diff <= te_avg && instance->pattern_counter > PSA_PATTERN_THRESHOLD_2) {
|
||||
instance->te_detected = te_avg;
|
||||
new_state = PSADecoderState4;
|
||||
instance->decode_data_low = 0;
|
||||
instance->decode_data_high = 0;
|
||||
instance->decode_count_bit = 0;
|
||||
manchester_advance(instance->manchester_state, ManchesterEventReset,
|
||||
&instance->manchester_state, NULL);
|
||||
instance->state = new_state;
|
||||
instance->pattern_counter = 0;
|
||||
instance->prev_duration = duration;
|
||||
return;
|
||||
@@ -975,67 +978,25 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati
|
||||
}
|
||||
|
||||
new_state = PSADecoderState0;
|
||||
instance->pattern_counter = 0;
|
||||
break;
|
||||
|
||||
case PSADecoderState4:
|
||||
case PSADecoderState4: {
|
||||
if(instance->decode_count_bit >= PSA_MAX_BITS) {
|
||||
new_state = PSADecoderState0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!level) {
|
||||
uint8_t manchester_input;
|
||||
bool decoded_bit = false;
|
||||
|
||||
if(duration < PSA_TE_SHORT_125) {
|
||||
tolerance = PSA_TE_SHORT_125 - duration;
|
||||
if(tolerance > PSA_TOLERANCE_49) {
|
||||
return;
|
||||
}
|
||||
manchester_input = ((level ^ 1) & 0x7f) << 1;
|
||||
} else {
|
||||
tolerance = duration - PSA_TE_SHORT_125;
|
||||
if(tolerance < PSA_TOLERANCE_50) {
|
||||
manchester_input = ((level ^ 1) & 0x7f) << 1;
|
||||
} else if(duration >= PSA_TE_LONG_250 && duration < 0x12c) {
|
||||
if(level == 0) {
|
||||
manchester_input = 6;
|
||||
} else {
|
||||
manchester_input = 4;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(manchester_advance(instance->manchester_state,
|
||||
(ManchesterEvent)manchester_input,
|
||||
&instance->manchester_state,
|
||||
&decoded_bit)) {
|
||||
uint32_t carry = (instance->decode_data_low >> 31) & 1;
|
||||
instance->decode_data_low = (instance->decode_data_low << 1) | (decoded_bit ? 1 : 0);
|
||||
instance->decode_data_high = (instance->decode_data_high << 1) | carry;
|
||||
instance->decode_count_bit++;
|
||||
|
||||
if(instance->decode_count_bit == PSA_KEY1_BITS) {
|
||||
instance->key1_low = instance->decode_data_low;
|
||||
instance->key1_high = instance->decode_data_high;
|
||||
instance->decode_data_low = 0;
|
||||
instance->decode_data_high = 0;
|
||||
}
|
||||
}
|
||||
} else if(level) {
|
||||
uint32_t end_diff;
|
||||
if(duration < PSA_TE_END_500) {
|
||||
end_diff = PSA_TE_END_500 - duration;
|
||||
} else {
|
||||
end_diff = duration - PSA_TE_END_500;
|
||||
}
|
||||
if(end_diff <= 99) {
|
||||
if(instance->decode_count_bit != PSA_KEY2_BITS) {
|
||||
return;
|
||||
}
|
||||
uint32_t te_s = instance->te_detected ? instance->te_detected : PSA_TE_SHORT_125;
|
||||
uint32_t te_l = te_s * 2;
|
||||
uint32_t te_tol = te_s / 2;
|
||||
uint32_t midpoint = (te_s + te_l) / 2;
|
||||
|
||||
// End marker check: HIGH pulse beyond long range at 80 bits
|
||||
if(level && instance->decode_count_bit == PSA_KEY2_BITS && duration > midpoint) {
|
||||
uint32_t end_expected = te_s * 4;
|
||||
uint32_t end_diff = psa_abs_diff(duration, end_expected);
|
||||
if(end_diff <= te_s * 2) {
|
||||
instance->validation_field = (uint16_t)(instance->decode_data_low & 0xFFFF);
|
||||
instance->key2_low = instance->decode_data_low;
|
||||
instance->key2_high = instance->decode_data_high;
|
||||
@@ -1052,7 +1013,6 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati
|
||||
instance->mode_serialize = 0x36;
|
||||
}
|
||||
|
||||
// Only fire callback if decrypted or validation nibble matches
|
||||
if(instance->decrypted != 0x50 &&
|
||||
(instance->validation_field & 0xf) != 0xa) {
|
||||
instance->decode_data_low = 0;
|
||||
@@ -1076,12 +1036,56 @@ void subghz_protocol_decoder_psa_feed(void* context, bool level, uint32_t durati
|
||||
new_state = PSADecoderState0;
|
||||
instance->state = new_state;
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
// Manchester decode: process BOTH high and low pulses (unlike original AM path)
|
||||
if(duration > te_l + te_tol) {
|
||||
if(duration > 10000) {
|
||||
new_state = PSADecoderState0;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t manchester_input;
|
||||
bool decoded_bit = false;
|
||||
|
||||
if(duration <= midpoint) {
|
||||
if(psa_abs_diff(duration, te_s) > te_tol) {
|
||||
return;
|
||||
}
|
||||
manchester_input = level ? ManchesterEventShortLow : ManchesterEventShortHigh;
|
||||
} else {
|
||||
if(psa_abs_diff(duration, te_l) > te_tol) {
|
||||
return;
|
||||
}
|
||||
manchester_input = level ? ManchesterEventLongLow : ManchesterEventLongHigh;
|
||||
}
|
||||
|
||||
if(instance->decode_count_bit < PSA_KEY2_BITS) {
|
||||
if(manchester_advance(instance->manchester_state,
|
||||
(ManchesterEvent)manchester_input,
|
||||
&instance->manchester_state,
|
||||
&decoded_bit)) {
|
||||
uint32_t carry = (instance->decode_data_low >> 31) & 1;
|
||||
// PSA AM uses inverted Manchester convention
|
||||
decoded_bit = !decoded_bit;
|
||||
instance->decode_data_low = (instance->decode_data_low << 1) | (decoded_bit ? 1 : 0);
|
||||
instance->decode_data_high = (instance->decode_data_high << 1) | carry;
|
||||
instance->decode_count_bit++;
|
||||
|
||||
if(instance->decode_count_bit == PSA_KEY1_BITS) {
|
||||
instance->key1_low = instance->decode_data_low;
|
||||
instance->key1_high = instance->decode_data_high;
|
||||
instance->decode_data_low = 0;
|
||||
instance->decode_data_high = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
instance->state = new_state;
|
||||
instance->prev_duration = duration;
|
||||
|
||||
Reference in New Issue
Block a user