#pragma once

#include <cstdint>

namespace irfox {

constexpr uint32_t kCarrierPeriodUs = 1000000U / 38000U;
constexpr uint32_t kBitActiveTakts = 25U;
constexpr uint32_t kBitPauseTakts = 12U;
constexpr uint32_t kBitTakts = kBitActiveTakts + kBitPauseTakts;
constexpr uint32_t kBitTimeUs = kBitTakts * kCarrierPeriodUs;
constexpr uint32_t kToleranceUs = 300U;

/** Мин. длительность плато (мкс) для потокового анти-глитча в анализаторе; согласовано с IR_INPUT_MIN_PULSE_US. */
constexpr uint32_t kMinFilteredPulseUs = 10U;

constexpr uint8_t kBitPerByte = 8U;
constexpr uint8_t kMsgBytes = 1;
constexpr uint8_t kAddrBytes = 2;
constexpr uint8_t kCrcBytes = 2;
constexpr uint8_t kPoly1 = 0x31;
constexpr uint8_t kPoly2 = 0x8C;
constexpr uint8_t kSyncBits = 3U;
constexpr uint8_t kBytePerPack = 31;
constexpr uint8_t kDataByteSizeMax =
	static_cast<uint8_t>(kMsgBytes + kAddrBytes + kAddrBytes + kBytePerPack + kCrcBytes);

constexpr uint8_t kPreambPulse = 3;
constexpr uint8_t kPreambFronts = kPreambPulse * 2U;

/** Отброс ложного подъёма после микро-LOW в паузе; зеркало IR_config.h (прошивка). */
#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)
{
	const uint32_t riseMax = riseSyncTimeUs + kToleranceUs;
	return riseMax * (8U + kSyncBits + 1U);
}

/** Как IR_DecoderRaw.h: aroundRise(t) → riseTimeMin < t && t < riseTimeMax (ветка STM32DMA). */
inline bool aroundRisePeriod(uint32_t periodUs, uint32_t riseSyncTimeUs)
{
	const uint32_t lo = riseSyncTimeUs > kToleranceUs ? riseSyncTimeUs - kToleranceUs : 0U;
	const uint32_t hi = riseSyncTimeUs + kToleranceUs;
	return lo < periodUs && periodUs < hi;
}

inline void irfoxGlitchPhaseNudgeUs(double edge_us, uint32_t rise_sync_us, double& prev_rise_us)
{
#if IRFOX_GLITCH_REJECT_PHASE_NUDGE
	if (!(edge_us > static_cast<double>(rise_sync_us)))
		return;
	const double nudged = edge_us - static_cast<double>(rise_sync_us);
	if (nudged > prev_rise_us && nudged < edge_us)
		prev_rise_us = nudged;
#else
	(void)edge_us;
	(void)rise_sync_us;
	(void)prev_rise_us;
#endif
}

} // namespace irfox
