From 3cf6c6e114ae3d5beabef3c7bcdbaee824433f4e Mon Sep 17 00:00:00 2001 From: RocketGod <57732082+RocketGod-git@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:11:27 -0800 Subject: [PATCH] Subaru decode added --- dist/proto_pirate.fap | Bin 45004 -> 47480 bytes protocols/protocol_items.c | 1 + protocols/protocol_items.h | 1 + protocols/subaru.c | 339 +++++++++++++++++++++++++++++++++++++ protocols/subaru.h | 27 +++ 5 files changed, 368 insertions(+) create mode 100644 protocols/subaru.c create mode 100644 protocols/subaru.h diff --git a/dist/proto_pirate.fap b/dist/proto_pirate.fap index 25357936b468aa4a4261ad01f2a349a4d8bfbc22..9f13758eec79f4c56fed1a2b61ff15e6f696daaf 100644 GIT binary patch delta 19092 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 delta 16912 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 x> 4) & 0x0F); + + uint8_t SER0 = KB[3]; + uint8_t SER1 = KB[1]; + uint8_t SER2 = KB[2]; + + uint8_t total_rot = 4 + lo; + for(uint8_t i = 0; i < total_rot; ++i) { + uint8_t t_bit = (SER0 >> 7) & 1; + SER0 = ((SER0 << 1) & 0xFE) | ((SER1 >> 7) & 1); + SER1 = ((SER1 << 1) & 0xFE) | ((SER2 >> 7) & 1); + SER2 = ((SER2 << 1) & 0xFE) | t_bit; + } + + uint8_t T1 = SER1 ^ REG_SH1; + uint8_t T2 = SER2 ^ REG_SH2; + + uint8_t hi = 0; + if((T1 & 0x10) == 0) hi |= 0x04; + if((T1 & 0x20) == 0) hi |= 0x08; + if((T2 & 0x80) == 0) hi |= 0x02; + if((T2 & 0x40) == 0) hi |= 0x01; + if((T1 & 0x01) == 0) hi |= 0x40; + if((T1 & 0x02) == 0) hi |= 0x80; + if((T2 & 0x08) == 0) hi |= 0x20; + if((T2 & 0x04) == 0) hi |= 0x10; + + *count = ((hi << 8) | lo) & 0xFFFF; +} + +static void subaru_add_bit(SubGhzProtocolDecoderSubaru* instance, bool bit) { + if(instance->bit_count < 64) { + uint8_t byte_idx = instance->bit_count / 8; + uint8_t bit_idx = 7 - (instance->bit_count % 8); + if(bit) { + instance->data[byte_idx] |= (1 << bit_idx); + } else { + instance->data[byte_idx] &= ~(1 << bit_idx); + } + instance->bit_count++; + } +} + +static bool subaru_process_data(SubGhzProtocolDecoderSubaru* instance) { + if(instance->bit_count < 64) { + return false; + } + + uint8_t* b = instance->data; + + instance->key = ((uint64_t)b[0] << 56) | ((uint64_t)b[1] << 48) | + ((uint64_t)b[2] << 40) | ((uint64_t)b[3] << 32) | + ((uint64_t)b[4] << 24) | ((uint64_t)b[5] << 16) | + ((uint64_t)b[6] << 8) | ((uint64_t)b[7]); + + instance->serial = ((uint32_t)b[1] << 16) | ((uint32_t)b[2] << 8) | b[3]; + instance->button = b[0] & 0x0F; + subaru_decode_count(b, &instance->count); + + return true; +} + +void* subghz_protocol_decoder_subaru_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderSubaru* instance = malloc(sizeof(SubGhzProtocolDecoderSubaru)); + instance->base.protocol = &subaru_protocol; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_subaru_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSubaru* instance = context; + free(instance); +} + +void subghz_protocol_decoder_subaru_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSubaru* instance = context; + instance->decoder.parser_step = SubaruDecoderStepReset; + instance->decoder.te_last = 0; + instance->header_count = 0; + instance->bit_count = 0; + memset(instance->data, 0, sizeof(instance->data)); +} + +void subghz_protocol_decoder_subaru_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderSubaru* instance = context; + + switch(instance->decoder.parser_step) { + case SubaruDecoderStepReset: + if(level && DURATION_DIFF(duration, subghz_protocol_subaru_const.te_long) < subghz_protocol_subaru_const.te_delta) { + instance->decoder.parser_step = SubaruDecoderStepCheckPreamble; + instance->decoder.te_last = duration; + instance->header_count = 1; + } + break; + + case SubaruDecoderStepCheckPreamble: + if(!level) { + if(DURATION_DIFF(duration, subghz_protocol_subaru_const.te_long) < subghz_protocol_subaru_const.te_delta) { + instance->header_count++; + } else if(duration > 2000 && duration < 3500) { + if(instance->header_count > 20) { + instance->decoder.parser_step = SubaruDecoderStepFoundGap; + } else { + instance->decoder.parser_step = SubaruDecoderStepReset; + } + } else { + instance->decoder.parser_step = SubaruDecoderStepReset; + } + } else { + if(DURATION_DIFF(duration, subghz_protocol_subaru_const.te_long) < subghz_protocol_subaru_const.te_delta) { + instance->decoder.te_last = duration; + instance->header_count++; + } else { + instance->decoder.parser_step = SubaruDecoderStepReset; + } + } + break; + + case SubaruDecoderStepFoundGap: + if(level && duration > 2000 && duration < 3500) { + instance->decoder.parser_step = SubaruDecoderStepFoundSync; + } else { + instance->decoder.parser_step = SubaruDecoderStepReset; + } + break; + + case SubaruDecoderStepFoundSync: + if(!level && DURATION_DIFF(duration, subghz_protocol_subaru_const.te_long) < subghz_protocol_subaru_const.te_delta) { + instance->decoder.parser_step = SubaruDecoderStepSaveDuration; + instance->bit_count = 0; + memset(instance->data, 0, sizeof(instance->data)); + } else { + instance->decoder.parser_step = SubaruDecoderStepReset; + } + break; + + case SubaruDecoderStepSaveDuration: + if(level) { + // HIGH pulse duration encodes the bit: + // Short HIGH (~800µs) = 1 + // Long HIGH (~1600µs) = 0 + if(DURATION_DIFF(duration, subghz_protocol_subaru_const.te_short) < subghz_protocol_subaru_const.te_delta) { + // Short HIGH = bit 1 + subaru_add_bit(instance, true); + instance->decoder.te_last = duration; + instance->decoder.parser_step = SubaruDecoderStepCheckDuration; + } else if(DURATION_DIFF(duration, subghz_protocol_subaru_const.te_long) < subghz_protocol_subaru_const.te_delta) { + // Long HIGH = bit 0 + subaru_add_bit(instance, false); + instance->decoder.te_last = duration; + instance->decoder.parser_step = SubaruDecoderStepCheckDuration; + } else if(duration > 3000) { + // End of transmission + if(instance->bit_count >= 64) { + if(subaru_process_data(instance)) { + instance->generic.data = instance->key; + instance->generic.data_count_bit = 64; + instance->generic.serial = instance->serial; + instance->generic.btn = instance->button; + instance->generic.cnt = instance->count; + + if(instance->base.callback) { + instance->base.callback(&instance->base, instance->base.context); + } + } + } + instance->decoder.parser_step = SubaruDecoderStepReset; + } else { + instance->decoder.parser_step = SubaruDecoderStepReset; + } + } else { + instance->decoder.parser_step = SubaruDecoderStepReset; + } + break; + + case SubaruDecoderStepCheckDuration: + if(!level) { + // LOW pulse - just validates timing, doesn't encode bit + if(DURATION_DIFF(duration, subghz_protocol_subaru_const.te_short) < subghz_protocol_subaru_const.te_delta || + DURATION_DIFF(duration, subghz_protocol_subaru_const.te_long) < subghz_protocol_subaru_const.te_delta) { + instance->decoder.parser_step = SubaruDecoderStepSaveDuration; + } else if(duration > 3000) { + // Gap - end of packet + if(instance->bit_count >= 64) { + if(subaru_process_data(instance)) { + instance->generic.data = instance->key; + instance->generic.data_count_bit = 64; + instance->generic.serial = instance->serial; + instance->generic.btn = instance->button; + instance->generic.cnt = instance->count; + + if(instance->base.callback) { + instance->base.callback(&instance->base, instance->base.context); + } + } + } + instance->decoder.parser_step = SubaruDecoderStepReset; + } else { + instance->decoder.parser_step = SubaruDecoderStepReset; + } + } else { + instance->decoder.parser_step = SubaruDecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_subaru_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderSubaru* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +SubGhzProtocolStatus subghz_protocol_decoder_subaru_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderSubaru* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +SubGhzProtocolStatus subghz_protocol_decoder_subaru_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderSubaru* instance = context; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_subaru_const.min_count_bit_for_found); +} + +void subghz_protocol_decoder_subaru_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderSubaru* instance = context; + + uint32_t key_hi = (uint32_t)(instance->key >> 32); + uint32_t key_lo = (uint32_t)(instance->key & 0xFFFFFFFF); + + furi_string_cat_printf( + output, + "%s %dbit\r\n" + "Key:%08lX%08lX\r\n" + "Sn:%06lX Btn:%X Cnt:%04X\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + key_hi, + key_lo, + instance->serial, + instance->button, + instance->count); +} \ No newline at end of file diff --git a/protocols/subaru.h b/protocols/subaru.h new file mode 100644 index 0000000..94c847e --- /dev/null +++ b/protocols/subaru.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SUBARU_PROTOCOL_NAME "Subaru" + +extern const SubGhzProtocol subaru_protocol; + +void* subghz_protocol_decoder_subaru_alloc(SubGhzEnvironment* environment); +void subghz_protocol_decoder_subaru_free(void* context); +void subghz_protocol_decoder_subaru_reset(void* context); +void subghz_protocol_decoder_subaru_feed(void* context, bool level, uint32_t duration); +uint8_t subghz_protocol_decoder_subaru_get_hash_data(void* context); +SubGhzProtocolStatus subghz_protocol_decoder_subaru_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); +SubGhzProtocolStatus subghz_protocol_decoder_subaru_deserialize(void* context, FlipperFormat* flipper_format); +void subghz_protocol_decoder_subaru_get_string(void* context, FuriString* output); \ No newline at end of file