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);
|
||||
}
|
||||
|
||||
// Обход кадра по границам ранов: между границами автомат выдаёт 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
|
||||
{
|
||||
st.sendLen = sendLen;
|
||||
@ -476,28 +499,27 @@ size_t IR_Encoder::buildGateRuns(const uint8_t *packet, uint8_t len, IR_TxGateRu
|
||||
st.currentBitSequence = bitHigh;
|
||||
|
||||
size_t runCount = 0;
|
||||
bool isActive = true;
|
||||
while (isActive)
|
||||
{
|
||||
bool gate = false;
|
||||
isActive = txEmitTick(st, sendBufferLocal, gate);
|
||||
|
||||
const bool ok = txWalkRuns(st, sendBufferLocal, [&](bool gate, uint32_t lenTicks) -> bool {
|
||||
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 0;
|
||||
return false;
|
||||
}
|
||||
outRuns[runCount].gate = gate;
|
||||
outRuns[runCount].lenTicks = 1U;
|
||||
outRuns[runCount].lenTicks = (uint16_t)lenTicks;
|
||||
runCount++;
|
||||
}
|
||||
}
|
||||
return runCount;
|
||||
return true;
|
||||
});
|
||||
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)
|
||||
@ -564,40 +586,29 @@ size_t IR_Encoder::buildPhysicalGateRuns(const uint8_t *packet, uint8_t len, IR_
|
||||
bool currentGate = false;
|
||||
uint32_t currentLogicalLen = 0;
|
||||
bool havePendingRun = false;
|
||||
bool isActive = true;
|
||||
while (isActive)
|
||||
const bool ok = txWalkRuns(st, sendBufferLocal, [&](bool gate, uint32_t lenTicks) -> bool {
|
||||
if (havePendingRun && currentGate == gate)
|
||||
{
|
||||
bool gate = false;
|
||||
isActive = txEmitTick(st, sendBufferLocal, gate);
|
||||
|
||||
if (!havePendingRun)
|
||||
currentLogicalLen += lenTicks;
|
||||
return true;
|
||||
}
|
||||
if (havePendingRun && !appendPhysicalRun(currentGate, currentLogicalLen, runCount))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
currentGate = gate;
|
||||
currentLogicalLen = 1U;
|
||||
currentLogicalLen = lenTicks;
|
||||
havePendingRun = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentGate == gate)
|
||||
{
|
||||
currentLogicalLen++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!appendPhysicalRun(currentGate, currentLogicalLen, runCount))
|
||||
return true;
|
||||
});
|
||||
if (!ok)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
currentGate = gate;
|
||||
currentLogicalLen = 1U;
|
||||
}
|
||||
|
||||
if (havePendingRun && !appendPhysicalRun(currentGate, currentLogicalLen, runCount))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return runCount;
|
||||
}
|
||||
|
||||
|
||||
@ -214,6 +214,8 @@ private:
|
||||
static bool txAdvanceBoundary(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);
|
||||
template <typename Emit>
|
||||
static bool txWalkRuns(TxFsmState &st, const uint8_t *sendBufferLocal, Emit emit);
|
||||
void loadTxFsmFromMembers(TxFsmState &st) const;
|
||||
void storeTxFsmToMembers(const TxFsmState &st);
|
||||
bool shouldUseBufferedIsr() const;
|
||||
|
||||
Reference in New Issue
Block a user