mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-09-21 20:39:35 +00:00
archive: freeze IR-protocol WIP before stepwise integration
This commit is contained in:
142
IR_config.h
142
IR_config.h
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user