archive: freeze IR-protocol WIP before stepwise integration

This commit is contained in:
2026-08-28 13:27:46 +03:00
parent 96ffb91b97
commit 57db9c35b8
18 changed files with 1848 additions and 391 deletions

View File

@ -15,8 +15,6 @@ constexpr size_t kDefaultDmaTxMaxStreams = 4U;
constexpr uint32_t kDmaTxIrqPriority = 8U;
/** Кольцевой буфер BSRR-слов для ISR-TX (как у DMA: два полублока). Чётное число. */
constexpr uint16_t kIsrTxBsrrWordCount = 256U;
/** Максимум RLE-сегментов для buildGateRuns при ISR-TX. */
constexpr size_t kIsrTxMaxGateRuns = 512U;
static_assert((kIsrTxBsrrWordCount & 1U) == 0U, "kIsrTxBsrrWordCount must be even");
}
@ -101,7 +99,7 @@ msg type:
                                //  ----------
                                // | xxx..... | = тип сообщения (биты 7..5)
                                // | ...xxxxx | = полная длина кадра в байтах (5 бит, 0..31, IR_MASK_MSG_INFO), не «31 бит» и не отдельный лимит «24 байта»
                                // Полезная нагрузка в data pack: до bytePerPack байт (см. #define bytePerPack).
// Полезная нагрузка в data pack: до irproto::kMaxDataPayloadBytes байт.
                                //  ---------- */
#define IR_MSG_BACK 0U // | 000...... | = Задний сигнал машинки
#define IR_MSG_ACCEPT 1U // | 001..... | = подтверждение
@ -111,7 +109,7 @@ msg type:
// #define IR_MSG_ 5U // | 101..... | = ??
#define IR_MSG_DATA_NOACCEPT 6U // | 110..... | = данные, не требующие подтверждения
#define IR_MSG_DATA_ACCEPT 7U // | 111..... | = данные требующие подтверждения
; /*   // ----------
/*   // ----------
/``````````````````````````````` подтверждение `````````````````````````````\      /``````````````````````````````````````` запрос ``````````````````````````````````\
                                                                                                                      
@ -159,15 +157,25 @@ msg type:
*/
#define IR_MASK_MSG_TYPE 0b00000111
#define IR_MASK_MSG_INFO 0b00011111
namespace irproto {
/** Three high header bits, shifted down, encode the message type. */
constexpr uint8_t kMessageTypeMask = 0x07U;
/** Five low header bits encode the complete on-wire frame length. */
constexpr uint8_t kWireFrameLengthBits = 5U;
constexpr uint8_t kWireFrameLengthMask =
static_cast<uint8_t>((1U << kWireFrameLengthBits) - 1U);
constexpr uint8_t kMaxWireFrameBytes = kWireFrameLengthMask;
}
// Source-compatible aliases. New code should use the typed irproto constants.
#define IR_MASK_MSG_TYPE (::irproto::kMessageTypeMask)
#define IR_MASK_MSG_INFO (::irproto::kWireFrameLengthMask)
/*
/////////////////////////////////////////////////////////////////////////////////////*/
typedef uint16_t crc_t;
// #define BRUTEFORCE_CHECK // Перепроверяет пакет на 1 битные ошибки //TODO: зависает
#define bytePerPack (31) // колличество байтов в пакете
#ifndef freeFrec
#define freeFrec false
#endif
@ -248,8 +256,6 @@ typedef uint16_t crc_t;
#define poly2 0x8C
#define syncBits 3U // количество битов синхронизации
#define dataByteSizeMax (msgBytes + addrBytes + addrBytes + bytePerPack + crcBytes)
#define preambFronts (preambPulse * 2) // количество фронтов преамбулы (Приём)
#define preambToggle ((bitPauseTakts * 2 + bitActiveTakts) * 2 - 1) // колличество переключений преамбулы (Передача)
@ -262,7 +268,123 @@ typedef uint16_t crc_t;
#define bitTakts (bitActiveTakts + bitPauseTakts) // Общая длительность бита в тактах
#define bitTime (bitTakts * carrierPeriod) // Общая длительность бита
#define tolerance 300U
namespace irproto {
constexpr uint8_t kDataFrameOverheadBytes = msgBytes + addrBytes + addrBytes + crcBytes;
constexpr uint8_t kBackFrameOverheadBytes = msgBytes + addrBytes + crcBytes;
constexpr uint8_t kBackToFrameOverheadBytes = msgBytes + addrBytes + addrBytes + crcBytes;
constexpr uint8_t kMaxDataPayloadBytes = kMaxWireFrameBytes - kDataFrameOverheadBytes;
constexpr uint8_t kMaxBackPayloadBytes = kMaxWireFrameBytes - kBackFrameOverheadBytes;
constexpr uint8_t kMaxBackToPayloadBytes = kMaxWireFrameBytes - kBackToFrameOverheadBytes;
/** RX timing geometry shared by adaptive and nominal decoder paths. */
constexpr uint16_t kRxTimingToleranceUs = 300U;
constexpr uint8_t kRxInterEdgeTimeoutGuardBitWindows = 1U;
constexpr uint8_t kRxInterEdgeTimeoutBitWindows =
static_cast<uint8_t>(bitPerByte + syncBits + kRxInterEdgeTimeoutGuardBitWindows);
constexpr uint8_t kRxSilenceTimeoutInterEdgeWindows = 2U;
/**
* Largest accepted rise-to-rise interval for one decoder byte window.
* adaptiveBitPeriodUs is riseSyncTime when free-frequency tracking is used.
*/
constexpr uint32_t rxInterEdgeTimeoutUs(uint32_t adaptiveBitPeriodUs)
{
return (adaptiveBitPeriodUs + static_cast<uint32_t>(kRxTimingToleranceUs)) *
static_cast<uint32_t>(kRxInterEdgeTimeoutBitWindows);
}
/** Silence after which an unfinished RX candidate is retired. */
constexpr uint32_t rxSilenceTimeoutUs(uint32_t adaptiveBitPeriodUs)
{
return rxInterEdgeTimeoutUs(adaptiveBitPeriodUs) *
static_cast<uint32_t>(kRxSilenceTimeoutInterEdgeWindows);
}
constexpr uint32_t microsToMillisCeil(uint32_t us)
{
return (us + 999U) / 1000U;
}
constexpr uint32_t kNominalRxInterEdgeTimeoutUs = rxInterEdgeTimeoutUs(bitTime);
constexpr uint32_t kNominalRxSilenceTimeoutUs = rxSilenceTimeoutUs(bitTime);
/**
* Deployed response/ACK turn-around policy.
*
* This is empirical, not a PHY invariant. Commit 1353ab6 replaced the older
* fixed 75 ms with a floating expression whose only reproducible result at the
* nominal PHY is 42 ms; no measurement or physical derivation was recorded.
* Keep the deployed value until a hardware gap campaign establishes a new
* channel-turn-around contract.
*/
constexpr uint16_t kDefaultResponseTurnaroundDelayMs = 42U;
/**
* Conservative logical run bound: preamble transitions plus two gate runs for
* every data/sync bit. Physical splitting for unusually large multiply values
* is reported by IR_TxPlan::gateRunCount and may require custom storage.
*/
constexpr size_t kMaxLogicalGateRuns =
static_cast<size_t>(preambPulse * 2U) +
static_cast<size_t>(kMaxWireFrameBytes) *
static_cast<size_t>((bitPerByte + syncBits) * 2U);
constexpr size_t kIsrTxMaxGateRuns = kMaxLogicalGateRuns;
/**
* Compile-time PHY storage contract.
*
* Every data and sync bit occupies bitTakts * 2 ticks on the logical
* 2*carrierFrec clock, independently of its value. A physical gate run is
* stored in uint16_t and can therefore split at UINT16_MAX ticks. The bound
* below includes the worst possible number of such split pieces; applications
* can size fixed DMA/ISR storage from the protocol instead of duplicating a
* packet-size constant.
*/
constexpr uint32_t kPreambleLogicalTicks =
static_cast<uint32_t>(preambPulse * 2U) *
static_cast<uint32_t>(preambToggle + 1U);
constexpr uint32_t kEncodedBitLogicalTicks =
static_cast<uint32_t>(bitTakts * 2U);
constexpr uint32_t kMaxLogicalTransmissionTicks =
kPreambleLogicalTicks +
static_cast<uint32_t>(kMaxWireFrameBytes) *
static_cast<uint32_t>(bitPerByte + syncBits) *
kEncodedBitLogicalTicks;
constexpr uint16_t normalizedCarrierMultiply(uint16_t multiply)
{
return multiply < 2U ? 2U : multiply;
}
constexpr uint64_t maxPhysicalTransmissionTicks(uint16_t multiply)
{
return (static_cast<uint64_t>(kMaxLogicalTransmissionTicks) *
static_cast<uint64_t>(normalizedCarrierMultiply(multiply)) +
1U) /
2U;
}
constexpr size_t maxPhysicalGateRunCapacity(uint16_t multiply)
{
return kMaxLogicalGateRuns +
static_cast<size_t>(maxPhysicalTransmissionTicks(multiply) /
static_cast<uint64_t>(UINT16_MAX));
}
static_assert(kMaxDataPayloadBytes == 24U, "IR DATA payload contract changed");
static_assert(kMaxBackPayloadBytes == 26U, "IR BACK payload contract changed");
static_assert(kNominalRxInterEdgeTimeoutUs == 15144U, "IR RX timeout contract changed");
static_assert(kNominalRxSilenceTimeoutUs == 30288U, "IR RX silence contract changed");
static_assert(kMaxLogicalTransmissionTicks <= UINT32_MAX,
"IR maximum transmission no longer fits IR_TxPlan");
}
// Deprecated source-compatible names. They are aliases only and no longer
// define independent storage/payload limits. bytePerPack historically meant
// 31; preserving that value avoids silently changing external sketches.
#define bytePerPack (::irproto::kMaxWireFrameBytes)
#define dataByteSizeMax (::irproto::kMaxWireFrameBytes)
#define IR_TIMING_TOLERANCE_US (::irproto::kRxTimingToleranceUs)
constexpr uint16_t test_all_Time = bitTime;
constexpr uint16_t test_all_Takts = bitTakts * 2;