protocol work
This commit is contained in:
+23
-10
@@ -4,6 +4,13 @@
|
||||
//! Each decoder processes level+duration pairs from the demodulator and optionally supports
|
||||
//! encoding (replay). Shared pieces: [common], [keeloq_common], [keys], [aut64].
|
||||
//!
|
||||
//! **Decoder selection (vs ProtoPirate)**
|
||||
//! ProtoPirate calls `subghz_receiver_decode(receiver, level, duration)` for each pulse; the
|
||||
//! Flipper SDK receiver (not in REFERENCES) feeds all registered decoders. There is no
|
||||
//! preamble-based decoder selection in the scene—only the decoder's own feed() logic (e.g. VAG
|
||||
//! Reset/Preamble1/Preamble2). We do the same: feed every pulse to all decoders that support the
|
||||
//! file frequency; whoever returns a valid frame is reported. No extra preamble filtering.
|
||||
//!
|
||||
//! **Manchester decoding**: Ford, Fiat, and common each have separate Manchester state machines
|
||||
//! (FordV0ManchesterState, FiatV0ManchesterState, CommonManchesterState in common.rs). They are
|
||||
//! not reused across protocols. Event conventions match the reference per protocol (e.g. Kia V5
|
||||
@@ -95,10 +102,10 @@ impl ProtocolRegistry {
|
||||
Box::new(kia_v3_v4::KiaV3V4Decoder::new()),
|
||||
Box::new(kia_v5::KiaV5Decoder::new()),
|
||||
Box::new(kia_v6::KiaV6Decoder::new()),
|
||||
// Other protocols (Ford before Subaru so 250/500µs Ford keyfobs decode as Ford)
|
||||
// VAG before Ford/Subaru so 500/1000µs VAG streams decode as VAG (ProtoPirate order has VAG after Ford/Subaru but Flipper likely feeds all decoders; KAT uses first-match so VAG must be tried earlier)
|
||||
Box::new(vag::VagDecoder::new()),
|
||||
Box::new(ford_v0::FordV0Decoder::new()),
|
||||
Box::new(subaru::SubaruDecoder::new()),
|
||||
Box::new(vag::VagDecoder::new()),
|
||||
Box::new(fiat_v0::FiatV0Decoder::new()),
|
||||
Box::new(suzuki::SuzukiDecoder::new()),
|
||||
Box::new(scher_khan::ScherKhanDecoder::new()),
|
||||
@@ -160,7 +167,9 @@ impl ProtocolRegistry {
|
||||
let level = if invert_level { !pair.level } else { pair.level };
|
||||
let duration_us = pair.duration_us;
|
||||
|
||||
let mut hit = None;
|
||||
// Feed this pulse to all decoders that support this frequency (Flipper-style).
|
||||
// Whoever actually produces a valid frame is reported; decoder order no longer decides.
|
||||
let mut hits: Vec<(String, DecodedSignal)> = Vec::new();
|
||||
for decoder in &mut self.decoders {
|
||||
let freq_supported = decoder
|
||||
.supported_frequencies()
|
||||
@@ -177,11 +186,10 @@ impl ProtocolRegistry {
|
||||
.protocol_display_name
|
||||
.as_deref()
|
||||
.unwrap_or_else(|| decoder.name());
|
||||
hit = Some((name.to_string(), decoded));
|
||||
break;
|
||||
hits.push((name.to_string(), decoded));
|
||||
}
|
||||
}
|
||||
if let Some((name, decoded)) = hit {
|
||||
if let Some((name, decoded)) = hits.into_iter().next() {
|
||||
let segment: Vec<LevelDuration> = pairs[segment_start..=i]
|
||||
.iter()
|
||||
.map(|p| LevelDuration::new(p.level, p.duration_us))
|
||||
@@ -212,6 +220,8 @@ impl ProtocolRegistry {
|
||||
let level = if invert_level { !pair.level } else { pair.level };
|
||||
let duration_us = pair.duration_us;
|
||||
|
||||
// Feed this pulse to all decoders; report first valid frame (Flipper-style).
|
||||
let mut hits: Vec<(String, DecodedSignal)> = Vec::new();
|
||||
for decoder in &mut self.decoders {
|
||||
let freq_supported = decoder
|
||||
.supported_frequencies()
|
||||
@@ -227,12 +237,15 @@ impl ProtocolRegistry {
|
||||
|
||||
if let Some(decoded) = decoder.feed(level, duration_us) {
|
||||
let name = decoded
|
||||
.protocol_display_name
|
||||
.as_deref()
|
||||
.unwrap_or_else(|| decoder.name());
|
||||
return Some((name.to_string(), decoded));
|
||||
.protocol_display_name
|
||||
.as_deref()
|
||||
.unwrap_or_else(|| decoder.name());
|
||||
hits.push((name.to_string(), decoded));
|
||||
}
|
||||
}
|
||||
if let Some((name, decoded)) = hits.into_iter().next() {
|
||||
return Some((name.to_string(), decoded));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
|
||||
+17
-9
@@ -18,6 +18,7 @@ use super::{ProtocolDecoder, ProtocolTiming, DecodedSignal};
|
||||
use super::aut64;
|
||||
use super::keys;
|
||||
use crate::radio::demodulator::LevelDuration;
|
||||
use tracing;
|
||||
|
||||
// Type 3/4 timing (used as default for ProtocolTiming)
|
||||
const TE_SHORT: u32 = 500;
|
||||
@@ -30,7 +31,8 @@ const MIN_COUNT_BIT: usize = 80;
|
||||
// Type 1/2 timing
|
||||
const TE_SHORT_12: u32 = 300;
|
||||
const TE_LONG_12: u32 = 600;
|
||||
const TE_DELTA_12: u32 = 80; // Preamble1/Data1 (ref vag.c 79/80)
|
||||
#[allow(dead_code)]
|
||||
const TE_DELTA_12: u32 = 80; // Preamble1/Data1 (ref vag.c 79/80); preamble now uses REF_PREAMBLE1_TOL
|
||||
|
||||
// Reference-aligned deltas (vag.c VAG_NEAR / VAG_TOL_300 79, VAG_TOL_500 120)
|
||||
const REF_RESET_DELTA: u32 = 79; // Reset: 300±79, 500±79 for Preamble2
|
||||
@@ -38,6 +40,8 @@ const REF_PREAMBLE_SYNC: u32 = 80; // Preamble2 counting: 500±80
|
||||
const REF_SYNC2_AB_DELTA: u32 = 79; // Sync2A/Sync2B: 500/1000/750±79 (ref VAG_NEAR(..., 79))
|
||||
const REF_SYNC2C_DELTA: u32 = 79; // Sync2C: 750±79
|
||||
const REF_GAP1_DELTA: u32 = 79; // Preamble1→Data1 gap 600µs ±79 (ref check_gap1)
|
||||
// Real-world Type 1/2: preamble often ~280–380µs; ref uses 79/80
|
||||
const REF_PREAMBLE1_TOL: u32 = 100; // 300±100 for Type 1/2 preamble lock/count
|
||||
|
||||
// TEA constants
|
||||
const TEA_DELTA: u32 = 0x9E3779B9;
|
||||
@@ -842,9 +846,9 @@ impl ProtocolDecoder for VagDecoder {
|
||||
if !level {
|
||||
return None;
|
||||
}
|
||||
// Matches vag.c: duration < 300 and (300-duration)<=79 -> Preamble1; else (duration-300)<=79 -> Preamble1; else (duration-300)>79 and 500±79 -> Preamble2
|
||||
// Matches vag.c: duration < 300 and (300-duration)<=tol -> Preamble1; else (duration-300)<=tol -> Preamble1; else 500±79 -> Preamble2. Use REF_PREAMBLE1_TOL for Type 1/2 lock.
|
||||
if duration < TE_SHORT_12 {
|
||||
if (TE_SHORT_12 - duration) > REF_RESET_DELTA {
|
||||
if (TE_SHORT_12 - duration) > REF_PREAMBLE1_TOL {
|
||||
return None;
|
||||
}
|
||||
// init_pattern1
|
||||
@@ -857,8 +861,8 @@ impl ProtocolDecoder for VagDecoder {
|
||||
self.vag_type = VagType::Unknown;
|
||||
self.te_last = duration;
|
||||
self.manchester_advance(ManchesterEvent::Reset);
|
||||
} else if duration.wrapping_sub(TE_SHORT_12) <= REF_RESET_DELTA {
|
||||
// Fall-through to init_pattern1 in ref (duration 300..380)
|
||||
} else if duration.wrapping_sub(TE_SHORT_12) <= REF_PREAMBLE1_TOL {
|
||||
// Fall-through to init_pattern1 in ref (duration 300..300+tol)
|
||||
self.step = DecoderStep::Preamble1;
|
||||
self.data_low = 0;
|
||||
self.data_high = 0;
|
||||
@@ -900,14 +904,14 @@ impl ProtocolDecoder for VagDecoder {
|
||||
TE_SHORT_12 - duration
|
||||
};
|
||||
|
||||
// Reference: (300-duration)<=79 or (duration-300)<80 -> count pair (check_preamble1_prev)
|
||||
if te_diff < TE_DELTA_12 {
|
||||
// Reference: (300-duration) or (duration-300) within tol -> count pair. Use REF_PREAMBLE1_TOL for real-world jitter.
|
||||
if te_diff <= REF_PREAMBLE1_TOL {
|
||||
let prev_diff = if self.te_last > TE_SHORT_12 {
|
||||
self.te_last - TE_SHORT_12
|
||||
} else {
|
||||
TE_SHORT_12 - self.te_last
|
||||
};
|
||||
if prev_diff <= REF_RESET_DELTA {
|
||||
if prev_diff <= REF_PREAMBLE1_TOL {
|
||||
self.te_last = duration;
|
||||
self.header_count += 1;
|
||||
return None;
|
||||
@@ -930,7 +934,7 @@ impl ProtocolDecoder for VagDecoder {
|
||||
} else {
|
||||
TE_SHORT_12 - self.te_last
|
||||
};
|
||||
if prev_diff <= REF_RESET_DELTA {
|
||||
if prev_diff <= REF_PREAMBLE1_TOL {
|
||||
self.step = DecoderStep::Data1;
|
||||
return None;
|
||||
}
|
||||
@@ -1005,6 +1009,10 @@ impl ProtocolDecoder for VagDecoder {
|
||||
self.data_count_bit = 80;
|
||||
|
||||
self.parse_data();
|
||||
tracing::debug!(
|
||||
"VAG Data1 decode: 80 bits, decrypted={} (report regardless of key)",
|
||||
self.decrypted
|
||||
);
|
||||
|
||||
let result = self.build_decoded_signal();
|
||||
self.data_low = 0;
|
||||
|
||||
Reference in New Issue
Block a user