This commit is contained in:
2026-04-07 15:08:02 +03:00
parent 7651f07e0a
commit c29fe2cf7c
3 changed files with 129 additions and 81 deletions

View File

@ -262,7 +262,7 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
const uint32_t rise_max_us = rise_sync_time_us + irfox::kToleranceUs;
/** Начало PRE-бабла: при первом подъёме пузыря метка ИК (активный низ) начинается со спада — берём prev_fall, если он близок. */
/** Визуализация: начало PRE с ближайшего спада в пределах ~3 битовых периодов (ИК-метка). */
auto new_bubble_preamble_start = [&](uint64_t edge_s, bool is_rising) -> uint64_t {
if (!is_rising)
return edge_s;
@ -278,9 +278,11 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
if (rising)
{
const uint32_t cand_rp = static_cast<uint32_t>(t_us - prev_rise_us);
const double delta_rp = t_us - prev_rise_us;
const uint32_t cand_rp = static_cast<uint32_t>(delta_rp);
const uint32_t cand_ht = static_cast<uint32_t>(t_us - prev_fall_us);
const uint32_t cand_lt = static_cast<uint32_t>(prev_fall_us - prev_rise_us);
#if IRFOX_SHORT_LOW_GLITCH_REJECT
const bool short_low_glitch =
is_recive && !is_preamb && cand_ht < (rise_min_us / 8U) && cand_lt >= rise_min_us &&
@ -288,9 +290,7 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
if (short_low_glitch)
{
err_other++;
#if IRFOX_GLITCH_REJECT_PHASE_NUDGE
irfox::irfoxGlitchPhaseNudgeUs(t_us, rise_sync_time_us, prev_rise_us);
#endif
last_processed_edge_us = t_us;
have_last_processed = true;
return;
@ -304,9 +304,7 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
if (micro_gap_rise)
{
err_other++;
#if IRFOX_GLITCH_REJECT_PHASE_NUDGE
irfox::irfoxGlitchPhaseNudgeUs(t_us, rise_sync_time_us, prev_rise_us);
#endif
last_processed_edge_us = t_us;
have_last_processed = true;
return;
@ -319,31 +317,32 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
have_last_processed = true;
return;
}
// Как IR_DecoderRaw::tick: до prev_rise_us = t_us, иначе ниже (t_us - prev_rise_us) на подъёме == 0.
// Визуализация PRE: длинная пауза, первый подъём — якорь от спада метки (декод как STM32DMA).
if (cand_rp > irmax * 2U && !is_recive_raw)
{
first_rx();
preamb_front_counter = static_cast<int8_t>(irfox::kPreambFronts - 1U);
is_preamb = true;
is_recive = true;
is_recive_raw = true;
is_wrong_pack = false;
preamble_bubble_start_sample_ = new_bubble_preamble_start(sample, true);
preamble_bubble_start_valid_ = true;
}
rise_period_anchor_sample_ = prev_rise_sample;
rise_period_us = cand_rp;
high_time_us = cand_ht;
low_time_us = cand_lt;
prev_rise_us = t_us;
prev_rise_sample = sample;
const bool accept_rise_timing =
(delta_rp > static_cast<double>(rise_max_us) / 4.0) || high_count != 0 || low_count != 0;
if (accept_rise_timing)
{
rise_period_anchor_sample_ = prev_rise_sample;
rise_period_us = cand_rp;
high_time_us = cand_ht;
low_time_us = cand_lt;
prev_rise_us = t_us;
prev_rise_sample = sample;
}
else
{
err_other++;
}
}
else
{
#if IRFOX_IN_MARK_DOUBLE_FALL_IGNORE
const double hi_since_rise = t_us - prev_rise_us;
const uint32_t mark_end_min_us = (rise_min_us * irfox::kBitActiveTakts) / irfox::kBitTakts;
#endif
if (t_us - prev_fall_us > rise_min_us / 4.0)
{
prev_fall_us = t_us;
@ -351,26 +350,23 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
}
else
{
#if IRFOX_IN_MARK_DOUBLE_FALL_IGNORE
if (!(is_recive && !is_preamb && hi_since_rise < static_cast<double>(mark_end_min_us)))
#endif
{
err_other++;
}
err_other++;
}
}
// Первый фронт после длинной тишины на спаде; на подъёме — cand_rp выше (до обновления prev_rise_us).
// IR_DecoderRaw::tick (STM32DMA): без firstRX(); старт сырого приёма только этим блоком.
if (t_us > prev_rise_us && (t_us - prev_rise_us) > irmax * 2.0 && !is_recive_raw)
{
first_rx();
preamb_front_counter = static_cast<int8_t>(irfox::kPreambFronts - 1U);
preamb_front_counter = static_cast<int8_t>(irfox::kPreambFronts - 1);
is_preamb = true;
is_recive = true;
is_recive_raw = true;
is_wrong_pack = false;
preamble_bubble_start_sample_ = new_bubble_preamble_start(sample, rising);
preamble_bubble_start_valid_ = true;
if (!preamble_bubble_start_valid_)
{
preamble_bubble_start_sample_ = new_bubble_preamble_start(sample, rising);
preamble_bubble_start_valid_ = true;
}
}
if (preamb_front_counter)
@ -390,10 +386,10 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
if (is_preamb)
{
is_preamb = false;
// IR_DecoderRaw: prevRise += risePeriod / 2 — prevRise на этом тике ещё время последнего подъёма
// (на спаде не обновлялся). В сэмплах: якорь = последний подъём + полпериода, не «спад + полпериод».
const uint64_t preamble_bubble_end_sample =
rising ? rise_period_anchor_sample_ : prev_rise_sample;
// IR_DecoderRaw: prevRise += risePeriod / 2 — фаза как в прошивке.
// Бабл PRE: до текущего фронта (sample1), чтобы охватить все kPreambPulse периодов (3 импульса),
// а не только до предыдущего подъёма (~2 периода).
const uint64_t preamble_bubble_end_sample = sample > 0 ? sample - 1 : sample;
prev_rise_us += rise_period_us / 2.0;
{
const double half_us = 0.5 * static_cast<double>(rise_period_us);
@ -460,16 +456,6 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
else
write_to_buffer(false, false, cell_start_s, cell_end_s, on_bit, on_pkt, IrFoxEmitBitMode::WithBubble);
}
#if IRFOX_RISE_GRAY_SINGLE_BIT_FALLBACK
else if (irfox::riseGraySingleBitFallback(rise_period_us, rise_sync_time_us))
{
err_other++;
if (high_time_us > low_time_us)
write_to_buffer(true, false, cell_start_s, cell_end_s, on_bit, on_pkt, IrFoxEmitBitMode::WithBubble);
else
write_to_buffer(false, false, cell_start_s, cell_end_s, on_bit, on_pkt, IrFoxEmitBitMode::WithBubble);
}
#endif
else
{
uint16_t hc = ceil_div_u16(static_cast<uint16_t>(high_time_us > 0xFFFF ? 0xFFFF : high_time_us),