Files
mayhem-firmware/firmware/baseband/fprotos/c-suzuki.hpp
T
2025-12-21 11:21:55 +01:00

121 lines
4.3 KiB
C++

#pragma once
#include "subcarbase.hpp"
#define SUZUKI_GAP_TIME 2000
#define SUZUKI_GAP_DELTA 400
typedef enum {
SuzukiDecoderStepReset = 0,
SuzukiDecoderStepFoundStartPulse,
SuzukiDecoderStepSaveDuration,
} SuzukiDecoderStep;
class FProtoSubCarSuzuki : public FProtoSubCarBase {
public:
FProtoSubCarSuzuki() {
sensorType = FPC_SUZUKI;
te_short = 250;
te_long = 500;
te_delta = 110;
min_count_bit_for_found = 64;
}
void suzuki_add_bit(uint32_t bit) {
uint32_t carry = data_low >> 31;
data_low = (data_low << 1) | bit;
data_high = (data_high << 1) | carry;
data_count_bit++;
}
void subghz_protocol_decoder_suzuki_reset() {
parser_step = SuzukiDecoderStepReset;
header_count = 0;
data_count_bit = 0;
data_low = 0;
data_high = 0;
}
void feed(bool level, uint32_t duration) {
switch (parser_step) {
case SuzukiDecoderStepReset:
// Wait for short HIGH pulse (~250µs) to start preamble
if (!level)
return;
if (DURATION_DIFF(duration, te_short) > te_delta) {
return;
}
data_low = 0;
data_high = 0;
parser_step = SuzukiDecoderStepFoundStartPulse;
header_count = 0;
data_count_bit = 0;
break;
case SuzukiDecoderStepFoundStartPulse:
if (level) {
// HIGH pulse
if (header_count < 257) {
// Still in preamble - just count
return;
}
// After preamble, look for long HIGH to start data
if (DURATION_DIFF(duration, te_long) < te_delta) {
parser_step = SuzukiDecoderStepSaveDuration;
suzuki_add_bit(1);
}
// Ignore short HIGHs after preamble until we see a long one
} else {
// LOW pulse - count as header if short
if (DURATION_DIFF(duration, te_short) < te_delta) {
te_last = duration;
header_count++;
} else {
parser_step = SuzukiDecoderStepReset;
}
}
break;
case SuzukiDecoderStepSaveDuration:
if (level) {
// HIGH pulse - determines bit value
// Long HIGH (~500µs) = 1, Short HIGH (~250µs) = 0
if (DURATION_DIFF(duration, te_long) < te_delta) {
suzuki_add_bit(1);
} else if (DURATION_DIFF(duration, te_short) < te_delta) {
suzuki_add_bit(0);
} else {
parser_step = SuzukiDecoderStepReset;
}
// Stay in this state for next bit
} else {
// LOW pulse - check for gap (end of transmission)
if (DURATION_DIFF(duration, SUZUKI_GAP_TIME) < SUZUKI_GAP_DELTA) {
// Gap found - end of transmission
if (data_count_bit == 64) {
data_count_bit = 64;
decode_data = ((uint64_t)data_high << 32) | (uint64_t)data_low;
// Check manufacturer nibble (should be 0xF)
uint8_t manufacturer = (data_high >> 28) & 0xF;
if (manufacturer == 0xF) {
// Extract fields
decode_data2 = 0; // Not used
if (callback) {
callback(this);
}
}
}
parser_step = SuzukiDecoderStepReset;
}
// Short LOW pulses are ignored - stay in this state
}
break;
}
}
uint16_t header_count = 0;
uint32_t data_high = 0;
uint32_t data_low = 0;
uint8_t data_count_bit = 0;
};