mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-04-28 03:08:08 +00:00
Analyzer
This commit is contained in:
@ -3,9 +3,11 @@
|
|||||||
#include "IrFoxDecoder.h"
|
#include "IrFoxDecoder.h"
|
||||||
#include <AnalyzerChannelData.h>
|
#include <AnalyzerChannelData.h>
|
||||||
#include <AnalyzerResults.h>
|
#include <AnalyzerResults.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
IrFoxAnalyzer::IrFoxAnalyzer()
|
IrFoxAnalyzer::IrFoxAnalyzer()
|
||||||
: Analyzer2(),
|
: Analyzer2(),
|
||||||
@ -72,6 +74,45 @@ void IrFoxAnalyzer::WorkerThread()
|
|||||||
IrFoxDecoder decoder;
|
IrFoxDecoder decoder;
|
||||||
decoder.reset();
|
decoder.reset();
|
||||||
|
|
||||||
|
/** Потоковый фильтр: убирает импульсы короче kMinFilteredPulseUs (иголки/дребезг в сэмплах). */
|
||||||
|
const U64 min_seg_samples =
|
||||||
|
std::max<U64>(1ULL, static_cast<U64>((static_cast<double>(irfox::kMinFilteredPulseUs) * 1e-6) * static_cast<double>(fs) + 0.5));
|
||||||
|
struct RawEdge
|
||||||
|
{
|
||||||
|
U64 sample;
|
||||||
|
bool rising;
|
||||||
|
};
|
||||||
|
std::vector<RawEdge> pending;
|
||||||
|
U64 last_dec_edge_sample = 0;
|
||||||
|
bool last_dec_edge_valid = false;
|
||||||
|
|
||||||
|
auto collapse_short_pairs = [&]() {
|
||||||
|
for (size_t i = 0; i + 1 < pending.size();)
|
||||||
|
{
|
||||||
|
if (pending[i + 1].sample - pending[i].sample < min_seg_samples)
|
||||||
|
{
|
||||||
|
pending.erase(pending.begin() + static_cast<std::ptrdiff_t>(i),
|
||||||
|
pending.begin() + static_cast<std::ptrdiff_t>(i + 2));
|
||||||
|
if (i > 0)
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto strip_vs_last_decoder = [&]() {
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
collapse_short_pairs();
|
||||||
|
if (!last_dec_edge_valid || pending.empty())
|
||||||
|
return;
|
||||||
|
if (pending[0].sample - last_dec_edge_sample >= min_seg_samples)
|
||||||
|
return;
|
||||||
|
pending.erase(pending.begin());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
U32 frames_since_commit = 0;
|
U32 frames_since_commit = 0;
|
||||||
const U32 kCommitBatch = 256;
|
const U32 kCommitBatch = 256;
|
||||||
|
|
||||||
@ -130,6 +171,43 @@ void IrFoxAnalyzer::WorkerThread()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto emit_confirmed_edges = [&]() {
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
collapse_short_pairs();
|
||||||
|
strip_vs_last_decoder();
|
||||||
|
if (pending.size() < 2)
|
||||||
|
return;
|
||||||
|
if (pending[1].sample - pending[0].sample < min_seg_samples)
|
||||||
|
continue;
|
||||||
|
decoder.processEdge(pending[0].sample, pending[0].rising, fs, on_bit, on_pkt);
|
||||||
|
last_dec_edge_sample = pending[0].sample;
|
||||||
|
last_dec_edge_valid = true;
|
||||||
|
pending.erase(pending.begin());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto flush_pending_tail = [&]() {
|
||||||
|
collapse_short_pairs();
|
||||||
|
strip_vs_last_decoder();
|
||||||
|
while (pending.size() >= 2 && pending[1].sample - pending[0].sample >= min_seg_samples)
|
||||||
|
{
|
||||||
|
decoder.processEdge(pending[0].sample, pending[0].rising, fs, on_bit, on_pkt);
|
||||||
|
last_dec_edge_sample = pending[0].sample;
|
||||||
|
last_dec_edge_valid = true;
|
||||||
|
pending.erase(pending.begin());
|
||||||
|
collapse_short_pairs();
|
||||||
|
strip_vs_last_decoder();
|
||||||
|
}
|
||||||
|
if (pending.size() == 1)
|
||||||
|
{
|
||||||
|
decoder.processEdge(pending[0].sample, pending[0].rising, fs, on_bit, on_pkt);
|
||||||
|
last_dec_edge_sample = pending[0].sample;
|
||||||
|
last_dec_edge_valid = true;
|
||||||
|
pending.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
CheckIfThreadShouldExit();
|
CheckIfThreadShouldExit();
|
||||||
@ -146,10 +224,12 @@ void IrFoxAnalyzer::WorkerThread()
|
|||||||
const BitState new_level = mIr->GetBitState();
|
const BitState new_level = mIr->GetBitState();
|
||||||
const bool rising = (new_level == BIT_HIGH);
|
const bool rising = (new_level == BIT_HIGH);
|
||||||
|
|
||||||
decoder.processEdge(edge_sample, rising, fs, on_bit, on_pkt);
|
pending.push_back(RawEdge{edge_sample, rising});
|
||||||
|
emit_confirmed_edges();
|
||||||
ReportProgress(edge_sample);
|
ReportProgress(edge_sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_pending_tail();
|
||||||
decoder.flushEnd(mIr->GetSampleNumber(), fs, on_bit, on_pkt);
|
decoder.flushEnd(mIr->GetSampleNumber(), fs, on_bit, on_pkt);
|
||||||
|
|
||||||
if (frames_since_commit != 0)
|
if (frames_since_commit != 0)
|
||||||
|
|||||||
@ -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;
|
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 {
|
auto new_bubble_preamble_start = [&](uint64_t edge_s, bool is_rising) -> uint64_t {
|
||||||
if (!is_rising)
|
if (!is_rising)
|
||||||
return edge_s;
|
return edge_s;
|
||||||
@ -278,9 +278,11 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
|
|||||||
|
|
||||||
if (rising)
|
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_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);
|
const uint32_t cand_lt = static_cast<uint32_t>(prev_fall_us - prev_rise_us);
|
||||||
|
|
||||||
#if IRFOX_SHORT_LOW_GLITCH_REJECT
|
#if IRFOX_SHORT_LOW_GLITCH_REJECT
|
||||||
const bool short_low_glitch =
|
const bool short_low_glitch =
|
||||||
is_recive && !is_preamb && cand_ht < (rise_min_us / 8U) && cand_lt >= rise_min_us &&
|
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)
|
if (short_low_glitch)
|
||||||
{
|
{
|
||||||
err_other++;
|
err_other++;
|
||||||
#if IRFOX_GLITCH_REJECT_PHASE_NUDGE
|
|
||||||
irfox::irfoxGlitchPhaseNudgeUs(t_us, rise_sync_time_us, prev_rise_us);
|
irfox::irfoxGlitchPhaseNudgeUs(t_us, rise_sync_time_us, prev_rise_us);
|
||||||
#endif
|
|
||||||
last_processed_edge_us = t_us;
|
last_processed_edge_us = t_us;
|
||||||
have_last_processed = true;
|
have_last_processed = true;
|
||||||
return;
|
return;
|
||||||
@ -304,9 +304,7 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
|
|||||||
if (micro_gap_rise)
|
if (micro_gap_rise)
|
||||||
{
|
{
|
||||||
err_other++;
|
err_other++;
|
||||||
#if IRFOX_GLITCH_REJECT_PHASE_NUDGE
|
|
||||||
irfox::irfoxGlitchPhaseNudgeUs(t_us, rise_sync_time_us, prev_rise_us);
|
irfox::irfoxGlitchPhaseNudgeUs(t_us, rise_sync_time_us, prev_rise_us);
|
||||||
#endif
|
|
||||||
last_processed_edge_us = t_us;
|
last_processed_edge_us = t_us;
|
||||||
have_last_processed = true;
|
have_last_processed = true;
|
||||||
return;
|
return;
|
||||||
@ -319,18 +317,18 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
|
|||||||
have_last_processed = true;
|
have_last_processed = true;
|
||||||
return;
|
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)
|
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_sample_ = new_bubble_preamble_start(sample, true);
|
||||||
preamble_bubble_start_valid_ = true;
|
preamble_bubble_start_valid_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_anchor_sample_ = prev_rise_sample;
|
||||||
rise_period_us = cand_rp;
|
rise_period_us = cand_rp;
|
||||||
high_time_us = cand_ht;
|
high_time_us = cand_ht;
|
||||||
@ -340,10 +338,11 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if IRFOX_IN_MARK_DOUBLE_FALL_IGNORE
|
err_other++;
|
||||||
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
|
else
|
||||||
|
{
|
||||||
if (t_us - prev_fall_us > rise_min_us / 4.0)
|
if (t_us - prev_fall_us > rise_min_us / 4.0)
|
||||||
{
|
{
|
||||||
prev_fall_us = t_us;
|
prev_fall_us = t_us;
|
||||||
@ -351,27 +350,24 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
|
|||||||
}
|
}
|
||||||
else
|
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)
|
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 - 1);
|
||||||
preamb_front_counter = static_cast<int8_t>(irfox::kPreambFronts - 1U);
|
|
||||||
is_preamb = true;
|
is_preamb = true;
|
||||||
is_recive = true;
|
is_recive = true;
|
||||||
is_recive_raw = true;
|
is_recive_raw = true;
|
||||||
is_wrong_pack = false;
|
is_wrong_pack = false;
|
||||||
|
if (!preamble_bubble_start_valid_)
|
||||||
|
{
|
||||||
preamble_bubble_start_sample_ = new_bubble_preamble_start(sample, rising);
|
preamble_bubble_start_sample_ = new_bubble_preamble_start(sample, rising);
|
||||||
preamble_bubble_start_valid_ = true;
|
preamble_bubble_start_valid_ = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (preamb_front_counter)
|
if (preamb_front_counter)
|
||||||
{
|
{
|
||||||
@ -390,10 +386,10 @@ void IrFoxDecoder::processEdge(uint64_t sample, bool rising, uint32_t fs, const
|
|||||||
if (is_preamb)
|
if (is_preamb)
|
||||||
{
|
{
|
||||||
is_preamb = false;
|
is_preamb = false;
|
||||||
// IR_DecoderRaw: prevRise += risePeriod / 2 — prevRise на этом тике ещё время последнего подъёма
|
// IR_DecoderRaw: prevRise += risePeriod / 2 — фаза как в прошивке.
|
||||||
// (на спаде не обновлялся). В сэмплах: якорь = последний подъём + полпериода, не «спад + полпериод».
|
// Бабл PRE: до текущего фронта (sample−1), чтобы охватить все kPreambPulse периодов (3 импульса),
|
||||||
const uint64_t preamble_bubble_end_sample =
|
// а не только до предыдущего подъёма (~2 периода).
|
||||||
rising ? rise_period_anchor_sample_ : prev_rise_sample;
|
const uint64_t preamble_bubble_end_sample = sample > 0 ? sample - 1 : sample;
|
||||||
prev_rise_us += rise_period_us / 2.0;
|
prev_rise_us += rise_period_us / 2.0;
|
||||||
{
|
{
|
||||||
const double half_us = 0.5 * static_cast<double>(rise_period_us);
|
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
|
else
|
||||||
write_to_buffer(false, false, cell_start_s, cell_end_s, on_bit, on_pkt, IrFoxEmitBitMode::WithBubble);
|
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
|
else
|
||||||
{
|
{
|
||||||
uint16_t hc = ceil_div_u16(static_cast<uint16_t>(high_time_us > 0xFFFF ? 0xFFFF : high_time_us),
|
uint16_t hc = ceil_div_u16(static_cast<uint16_t>(high_time_us > 0xFFFF ? 0xFFFF : high_time_us),
|
||||||
|
|||||||
@ -11,25 +11,8 @@ constexpr uint32_t kBitTakts = kBitActiveTakts + kBitPauseTakts;
|
|||||||
constexpr uint32_t kBitTimeUs = kBitTakts * kCarrierPeriodUs;
|
constexpr uint32_t kBitTimeUs = kBitTakts * kCarrierPeriodUs;
|
||||||
constexpr uint32_t kToleranceUs = 300U;
|
constexpr uint32_t kToleranceUs = 300U;
|
||||||
|
|
||||||
/** Синхронно с IR_config.h: IR_SHORT_LOW_GLITCH_REJECT (1 = включено, как на железе). */
|
/** Мин. длительность плато (мкс) для потокового анти-глитча в анализаторе; согласовано с IR_INPUT_MIN_PULSE_US. */
|
||||||
#ifndef IRFOX_SHORT_LOW_GLITCH_REJECT
|
constexpr uint32_t kMinFilteredPulseUs = 10U;
|
||||||
#define IRFOX_SHORT_LOW_GLITCH_REJECT 1
|
|
||||||
#endif
|
|
||||||
#ifndef IRFOX_RISE_INCLUSIVE_AROUND
|
|
||||||
#define IRFOX_RISE_INCLUSIVE_AROUND 1
|
|
||||||
#endif
|
|
||||||
#ifndef IRFOX_RISE_GRAY_SINGLE_BIT_FALLBACK
|
|
||||||
#define IRFOX_RISE_GRAY_SINGLE_BIT_FALLBACK 0
|
|
||||||
#endif
|
|
||||||
#ifndef IRFOX_GLITCH_REJECT_PHASE_NUDGE
|
|
||||||
#define IRFOX_GLITCH_REJECT_PHASE_NUDGE 1
|
|
||||||
#endif
|
|
||||||
#ifndef IRFOX_MICRO_GAP_RISE_REJECT
|
|
||||||
#define IRFOX_MICRO_GAP_RISE_REJECT 1
|
|
||||||
#endif
|
|
||||||
#ifndef IRFOX_IN_MARK_DOUBLE_FALL_IGNORE
|
|
||||||
#define IRFOX_IN_MARK_DOUBLE_FALL_IGNORE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
constexpr uint8_t kBitPerByte = 8U;
|
constexpr uint8_t kBitPerByte = 8U;
|
||||||
constexpr uint8_t kMsgBytes = 1;
|
constexpr uint8_t kMsgBytes = 1;
|
||||||
@ -45,32 +28,31 @@ constexpr uint8_t kDataByteSizeMax =
|
|||||||
constexpr uint8_t kPreambPulse = 3;
|
constexpr uint8_t kPreambPulse = 3;
|
||||||
constexpr uint8_t kPreambFronts = kPreambPulse * 2U;
|
constexpr uint8_t kPreambFronts = kPreambPulse * 2U;
|
||||||
|
|
||||||
|
/** Отброс ложного подъёма после микро-LOW в паузе (как расширенный IR_DecoderRaw::tick). */
|
||||||
|
#ifndef IRFOX_SHORT_LOW_GLITCH_REJECT
|
||||||
|
#define IRFOX_SHORT_LOW_GLITCH_REJECT 1
|
||||||
|
#endif
|
||||||
|
#ifndef IRFOX_GLITCH_REJECT_PHASE_NUDGE
|
||||||
|
#define IRFOX_GLITCH_REJECT_PHASE_NUDGE 1
|
||||||
|
#endif
|
||||||
|
#ifndef IRFOX_MICRO_GAP_RISE_REJECT
|
||||||
|
#define IRFOX_MICRO_GAP_RISE_REJECT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
inline uint32_t irTimeoutUs(uint32_t riseSyncTimeUs)
|
inline uint32_t irTimeoutUs(uint32_t riseSyncTimeUs)
|
||||||
{
|
{
|
||||||
const uint32_t riseMax = riseSyncTimeUs + kToleranceUs;
|
const uint32_t riseMax = riseSyncTimeUs + kToleranceUs;
|
||||||
return riseMax * (8U + kSyncBits + 1U);
|
return riseMax * (8U + kSyncBits + 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Как IR_DecoderRaw.h: aroundRise(t) → riseTimeMin < t && t < riseTimeMax (ветка STM32DMA). */
|
||||||
inline bool aroundRisePeriod(uint32_t periodUs, uint32_t riseSyncTimeUs)
|
inline bool aroundRisePeriod(uint32_t periodUs, uint32_t riseSyncTimeUs)
|
||||||
{
|
{
|
||||||
const uint32_t lo = riseSyncTimeUs > kToleranceUs ? riseSyncTimeUs - kToleranceUs : 0U;
|
const uint32_t lo = riseSyncTimeUs > kToleranceUs ? riseSyncTimeUs - kToleranceUs : 0U;
|
||||||
const uint32_t hi = riseSyncTimeUs + kToleranceUs;
|
const uint32_t hi = riseSyncTimeUs + kToleranceUs;
|
||||||
#if IRFOX_RISE_INCLUSIVE_AROUND
|
|
||||||
return lo <= periodUs && periodUs <= hi;
|
|
||||||
#else
|
|
||||||
return lo < periodUs && periodUs < hi;
|
return lo < periodUs && periodUs < hi;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Синхронно с IR_config.h: IR_RISE_GRAY_SINGLE_BIT_FALLBACK. */
|
|
||||||
inline bool riseGraySingleBitFallback(uint32_t periodUs, uint32_t riseSyncTimeUs)
|
|
||||||
{
|
|
||||||
const uint32_t hi = riseSyncTimeUs + kToleranceUs;
|
|
||||||
const uint32_t twice = riseSyncTimeUs * 2U;
|
|
||||||
return periodUs > hi && periodUs <= twice;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Синхронно с IR_config.h: IR_GLITCH_REJECT_PHASE_NUDGE. */
|
|
||||||
inline void irfoxGlitchPhaseNudgeUs(double edge_us, uint32_t rise_sync_us, double& prev_rise_us)
|
inline void irfoxGlitchPhaseNudgeUs(double edge_us, uint32_t rise_sync_us, double& prev_rise_us)
|
||||||
{
|
{
|
||||||
#if IRFOX_GLITCH_REJECT_PHASE_NUDGE
|
#if IRFOX_GLITCH_REJECT_PHASE_NUDGE
|
||||||
|
|||||||
Reference in New Issue
Block a user