mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-09-18 19:13:58 +00:00
perf(tx): таблица ранов кадра строится по границам ранов, а не по тактам несущей
buildGateRuns/buildPhysicalGateRuns крутили автомат передачи по одному такту (пинг 10 байт = 8728 тактов) — на 12 МГц это ~30 мс между вызовом send и стартом DMA, на каждой передаче (задний ~20 мс). Обход по границам (txWalkRuns: ран = toggleCounter+1 тактов уровня state) даёт ту же последовательность за число шагов = число ранов (225). Эквивалентность проверена на хосте: 12480 случаев, len 1..38, множитель 2..8, логические и физические раны совпадают бит-в-бит (len=39 — чтение за буфером в sync-фазе автомата у обеих версий, на эфире ≤31). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeA1K5dBUKrnoXVwyoVjzq
This commit is contained in:
@ -352,6 +352,29 @@ bool IR_Encoder::txEmitTick(TxFsmState &st, const uint8_t *sendBufferLocal, bool
|
|||||||
return txAdvanceAfterOutput(st, sendBufferLocal);
|
return txAdvanceAfterOutput(st, sendBufferLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Обход кадра по границам ранов: между границами автомат выдаёт st.toggleCounter+1 тактов
|
||||||
|
// уровня st.state (txAdvanceAfterOutput считает toggleCounter до нуля, затем txAdvanceBoundary
|
||||||
|
// открывает следующий ран). Даёт ту же последовательность тактов, что потиковый обход, но за
|
||||||
|
// число шагов = число ранов (пинг: ~230 вместо ~8700 тактов — на 12 МГц это ~30 мс перед стартом DMA).
|
||||||
|
template <typename Emit>
|
||||||
|
bool IR_Encoder::txWalkRuns(TxFsmState &st, const uint8_t *sendBufferLocal, Emit emit)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const bool gate = st.state;
|
||||||
|
const uint32_t lenTicks = (uint32_t)st.toggleCounter + 1U;
|
||||||
|
if (!emit(gate, lenTicks))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
st.toggleCounter = 0;
|
||||||
|
if (!txAdvanceBoundary(st, sendBufferLocal))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void IR_Encoder::loadTxFsmFromMembers(TxFsmState &st) const
|
void IR_Encoder::loadTxFsmFromMembers(TxFsmState &st) const
|
||||||
{
|
{
|
||||||
st.sendLen = sendLen;
|
st.sendLen = sendLen;
|
||||||
@ -476,28 +499,27 @@ size_t IR_Encoder::buildGateRuns(const uint8_t *packet, uint8_t len, IR_TxGateRu
|
|||||||
st.currentBitSequence = bitHigh;
|
st.currentBitSequence = bitHigh;
|
||||||
|
|
||||||
size_t runCount = 0;
|
size_t runCount = 0;
|
||||||
bool isActive = true;
|
const bool ok = txWalkRuns(st, sendBufferLocal, [&](bool gate, uint32_t lenTicks) -> bool {
|
||||||
while (isActive)
|
|
||||||
{
|
|
||||||
bool gate = false;
|
|
||||||
isActive = txEmitTick(st, sendBufferLocal, gate);
|
|
||||||
|
|
||||||
if (runCount > 0 && outRuns[runCount - 1].gate == gate)
|
if (runCount > 0 && outRuns[runCount - 1].gate == gate)
|
||||||
{
|
{
|
||||||
outRuns[runCount - 1].lenTicks = (uint16_t)(outRuns[runCount - 1].lenTicks + 1U);
|
const uint32_t merged = (uint32_t)outRuns[runCount - 1].lenTicks + lenTicks;
|
||||||
|
if (merged > 65535U)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
outRuns[runCount - 1].lenTicks = (uint16_t)merged;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (runCount >= maxRuns || lenTicks > 65535U)
|
||||||
{
|
{
|
||||||
if (runCount >= maxRuns)
|
return false;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
outRuns[runCount].gate = gate;
|
outRuns[runCount].gate = gate;
|
||||||
outRuns[runCount].lenTicks = 1U;
|
outRuns[runCount].lenTicks = (uint16_t)lenTicks;
|
||||||
runCount++;
|
runCount++;
|
||||||
}
|
return true;
|
||||||
}
|
});
|
||||||
return runCount;
|
return ok ? runCount : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t IR_Encoder::buildPhysicalGateRuns(const uint8_t *packet, uint8_t len, IR_TxGateRun *outRuns, size_t maxRuns, uint16_t multiply)
|
size_t IR_Encoder::buildPhysicalGateRuns(const uint8_t *packet, uint8_t len, IR_TxGateRun *outRuns, size_t maxRuns, uint16_t multiply)
|
||||||
@ -564,40 +586,29 @@ size_t IR_Encoder::buildPhysicalGateRuns(const uint8_t *packet, uint8_t len, IR_
|
|||||||
bool currentGate = false;
|
bool currentGate = false;
|
||||||
uint32_t currentLogicalLen = 0;
|
uint32_t currentLogicalLen = 0;
|
||||||
bool havePendingRun = false;
|
bool havePendingRun = false;
|
||||||
bool isActive = true;
|
const bool ok = txWalkRuns(st, sendBufferLocal, [&](bool gate, uint32_t lenTicks) -> bool {
|
||||||
while (isActive)
|
if (havePendingRun && currentGate == gate)
|
||||||
{
|
{
|
||||||
bool gate = false;
|
currentLogicalLen += lenTicks;
|
||||||
isActive = txEmitTick(st, sendBufferLocal, gate);
|
return true;
|
||||||
|
}
|
||||||
if (!havePendingRun)
|
if (havePendingRun && !appendPhysicalRun(currentGate, currentLogicalLen, runCount))
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
currentGate = gate;
|
currentGate = gate;
|
||||||
currentLogicalLen = 1U;
|
currentLogicalLen = lenTicks;
|
||||||
havePendingRun = true;
|
havePendingRun = true;
|
||||||
continue;
|
return true;
|
||||||
}
|
});
|
||||||
|
if (!ok)
|
||||||
if (currentGate == gate)
|
|
||||||
{
|
|
||||||
currentLogicalLen++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!appendPhysicalRun(currentGate, currentLogicalLen, runCount))
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentGate = gate;
|
|
||||||
currentLogicalLen = 1U;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (havePendingRun && !appendPhysicalRun(currentGate, currentLogicalLen, runCount))
|
if (havePendingRun && !appendPhysicalRun(currentGate, currentLogicalLen, runCount))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return runCount;
|
return runCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -214,6 +214,8 @@ private:
|
|||||||
static bool txAdvanceBoundary(TxFsmState &st, const uint8_t *sendBufferLocal);
|
static bool txAdvanceBoundary(TxFsmState &st, const uint8_t *sendBufferLocal);
|
||||||
static bool txAdvanceAfterOutput(TxFsmState &st, const uint8_t *sendBufferLocal);
|
static bool txAdvanceAfterOutput(TxFsmState &st, const uint8_t *sendBufferLocal);
|
||||||
static bool txEmitTick(TxFsmState &st, const uint8_t *sendBufferLocal, bool &gateOut);
|
static bool txEmitTick(TxFsmState &st, const uint8_t *sendBufferLocal, bool &gateOut);
|
||||||
|
template <typename Emit>
|
||||||
|
static bool txWalkRuns(TxFsmState &st, const uint8_t *sendBufferLocal, Emit emit);
|
||||||
void loadTxFsmFromMembers(TxFsmState &st) const;
|
void loadTxFsmFromMembers(TxFsmState &st) const;
|
||||||
void storeTxFsmToMembers(const TxFsmState &st);
|
void storeTxFsmToMembers(const TxFsmState &st);
|
||||||
bool shouldUseBufferedIsr() const;
|
bool shouldUseBufferedIsr() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user