mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-04-28 03:08:08 +00:00
Refactor IR decoder and encoder for improved pulse filtering and ISR handling. Removed unused filtered sub-buffer, updated pulse filter methods, and added support for buffered ISR storage in the encoder. Enhanced documentation for clarity on DMA TX backend and ISR modes.
This commit is contained in:
154
IR_Encoder.cpp
154
IR_Encoder.cpp
@ -1,7 +1,24 @@
|
||||
#include "IR_Encoder.h"
|
||||
#include "IR_DecoderRaw.h"
|
||||
#include "IrTxIsrBufferedStorage.h"
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define IRPROTO_PRAGMA_MESSAGE(text) __pragma(message(text))
|
||||
#else
|
||||
#define IRPROTO_PRAGMA_MESSAGE(text) _Pragma(#text)
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_STM32)
|
||||
#if defined(STM32G4xx)
|
||||
IRPROTO_PRAGMA_MESSAGE(message("[IR-protocol] TX backends: ISR + built-in DMA"))
|
||||
#elif defined(STM32F4xx)
|
||||
IRPROTO_PRAGMA_MESSAGE(message("[IR-protocol] TX backends: ISR only"))
|
||||
#else
|
||||
IRPROTO_PRAGMA_MESSAGE(message("[IR-protocol] TX backends: ISR"))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LoopOut 12
|
||||
#define ISR_Out 10
|
||||
#define TestOut 13
|
||||
@ -14,6 +31,7 @@ IR_Encoder::IR_Encoder(uint8_t pin, uint16_t addr, IR_DecoderRaw *decPair, bool
|
||||
{
|
||||
setPin(pin);
|
||||
id = addr;
|
||||
txIsrMode_ = txIsrLegacyMode_ ? TxIsrMode::Legacy : TxIsrMode::Buffered;
|
||||
this->decPair = decPair;
|
||||
if (decPair != nullptr)
|
||||
{
|
||||
@ -45,7 +63,7 @@ HardwareTimer* IR_Encoder::IR_Timer = nullptr;
|
||||
IR_Encoder::ExternalTxStartFn IR_Encoder::externalTxStartFn = nullptr;
|
||||
IR_Encoder::ExternalTxBusyFn IR_Encoder::externalTxBusyFn = nullptr;
|
||||
void *IR_Encoder::externalTxCtx = nullptr;
|
||||
bool IR_Encoder::txIsrLegacyMode_ = false;
|
||||
bool IR_Encoder::txIsrLegacyMode_ = true;
|
||||
uint16_t IR_Encoder::s_carrierMultiply = 2;
|
||||
|
||||
void IR_Encoder::setCarrierMultiply(uint16_t multiply)
|
||||
@ -146,6 +164,11 @@ bool IR_Encoder::scaleGateRunsToPhysical(IR_TxGateRun* runs, size_t* ioCount, si
|
||||
void IR_Encoder::setTxIsrLegacyMode(bool legacy)
|
||||
{
|
||||
txIsrLegacyMode_ = legacy;
|
||||
const TxIsrMode mode = legacy ? TxIsrMode::Legacy : TxIsrMode::Buffered;
|
||||
for (IR_Encoder *p = head; p != nullptr; p = p->next)
|
||||
{
|
||||
p->txIsrMode_ = mode;
|
||||
}
|
||||
}
|
||||
|
||||
bool IR_Encoder::txIsrLegacyMode()
|
||||
@ -153,6 +176,54 @@ bool IR_Encoder::txIsrLegacyMode()
|
||||
return txIsrLegacyMode_;
|
||||
}
|
||||
|
||||
void IR_Encoder::attachBufferedIsrStorage(IrTxIsrBufferedStorageBase& storage)
|
||||
{
|
||||
txBufferedCtx_ = &storage;
|
||||
}
|
||||
|
||||
void IR_Encoder::detachBufferedIsrStorage()
|
||||
{
|
||||
txBufferedCtx_ = nullptr;
|
||||
if (!isSending)
|
||||
{
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
txUseBufferedIsr_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool IR_Encoder::hasBufferedIsrStorage() const
|
||||
{
|
||||
return txBufferedCtx_ != nullptr && txBufferedCtx_->isValid();
|
||||
}
|
||||
|
||||
void IR_Encoder::enableBufferedIsr(IrTxIsrBufferedStorageBase& storage)
|
||||
{
|
||||
attachBufferedIsrStorage(storage);
|
||||
txIsrMode_ = TxIsrMode::Buffered;
|
||||
}
|
||||
|
||||
void IR_Encoder::disableBufferedIsr()
|
||||
{
|
||||
txIsrMode_ = TxIsrMode::Legacy;
|
||||
if (!isSending)
|
||||
{
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
txUseBufferedIsr_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
IR_Encoder::TxIsrMode IR_Encoder::txIsrMode() const
|
||||
{
|
||||
return txIsrMode_;
|
||||
}
|
||||
|
||||
bool IR_Encoder::shouldUseBufferedIsr() const
|
||||
{
|
||||
return txIsrMode_ == TxIsrMode::Buffered &&
|
||||
txBufferedCtx_ != nullptr &&
|
||||
txBufferedCtx_->isValid();
|
||||
}
|
||||
|
||||
bool IR_Encoder::txAdvanceBoundary(TxFsmState &st, const uint8_t *sendBufferLocal)
|
||||
{
|
||||
while (true)
|
||||
@ -336,6 +407,8 @@ void IR_Encoder::externalFinishSend()
|
||||
}
|
||||
|
||||
isSending = false;
|
||||
txUseBufferedIsr_ = false;
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
refreshBlindDecoderMuteState();
|
||||
}
|
||||
|
||||
@ -704,6 +777,8 @@ void IR_Encoder::rawSend(uint8_t *ptr, uint8_t len)
|
||||
}
|
||||
|
||||
sendLen = len;
|
||||
txUseBufferedIsr_ = false;
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
isSending = true;
|
||||
refreshBlindDecoderMuteState();
|
||||
|
||||
@ -727,7 +802,11 @@ void IR_Encoder::rawSend(uint8_t *ptr, uint8_t len)
|
||||
}
|
||||
sendLen = len;
|
||||
|
||||
if (txIsrLegacyMode_)
|
||||
const bool useBufferedIsr = shouldUseBufferedIsr();
|
||||
txUseBufferedIsr_ = useBufferedIsr;
|
||||
txActiveBufferedCtx_ = useBufferedIsr ? txBufferedCtx_ : nullptr;
|
||||
|
||||
if (!useBufferedIsr)
|
||||
{
|
||||
toggleCounter = preambToggle;
|
||||
dataBitCounter = bitPerByte - 1;
|
||||
@ -756,22 +835,36 @@ void IR_Encoder::rawSend(uint8_t *ptr, uint8_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
size_t nRuns = buildGateRuns(sendBuffer, len, txGateRuns_, irproto::kIsrTxMaxGateRuns);
|
||||
if (nRuns == 0U)
|
||||
IrTxIsrBufferedStorageBase* buf = txActiveBufferedCtx_;
|
||||
if (buf == nullptr || !buf->isValid())
|
||||
{
|
||||
txUseBufferedIsr_ = false;
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
return;
|
||||
}
|
||||
if (!scaleGateRunsToPhysical(txGateRuns_, &nRuns, irproto::kIsrTxMaxGateRuns, carrierMultiply()))
|
||||
|
||||
buf->resetRuntimeState();
|
||||
|
||||
size_t nRuns = buildGateRuns(sendBuffer, len, buf->gateRuns, buf->maxGateRuns);
|
||||
if (nRuns == 0U)
|
||||
{
|
||||
txUseBufferedIsr_ = false;
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
return;
|
||||
}
|
||||
if (!scaleGateRunsToPhysical(buf->gateRuns, &nRuns, buf->maxGateRuns, carrierMultiply()))
|
||||
{
|
||||
txUseBufferedIsr_ = false;
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t total = 0;
|
||||
for (size_t i = 0; i < nRuns; i++)
|
||||
{
|
||||
total += txGateRuns_[i].lenTicks;
|
||||
total += buf->gateRuns[i].lenTicks;
|
||||
}
|
||||
txBsrrTotalTicks_ = total;
|
||||
buf->totalTicks = total;
|
||||
|
||||
const uint32_t setW = (uint32_t)mask;
|
||||
const uint32_t resetW = ((uint32_t)mask) << 16U;
|
||||
@ -780,13 +873,8 @@ void IR_Encoder::rawSend(uint8_t *ptr, uint8_t len)
|
||||
const uint16_t cap = maxPowerNumerator();
|
||||
txPowerSnap_ = (powerNumerator_ > cap) ? cap : powerNumerator_;
|
||||
}
|
||||
txBsrrWave_.configure(setW, resetW, txGateRuns_, nRuns, txMultiplySnap_, txPowerSnap_);
|
||||
|
||||
txBsrrHalfLen_ = (uint16_t)(irproto::kIsrTxBsrrWordCount / 2U);
|
||||
txBsrrWave_.fill(txBsrrWords_, irproto::kIsrTxBsrrWordCount);
|
||||
|
||||
txBsrrReadIdx_ = 0;
|
||||
txBsrrTicksSent_ = 0;
|
||||
buf->wave.configure(setW, resetW, buf->gateRuns, nRuns, txMultiplySnap_, txPowerSnap_);
|
||||
buf->wave.fill(buf->bsrrWords, buf->wordCount);
|
||||
|
||||
isSending = true;
|
||||
refreshBlindDecoderMuteState();
|
||||
@ -815,7 +903,7 @@ void IR_Encoder::_isr()
|
||||
if (port == nullptr)
|
||||
return;
|
||||
|
||||
if (txIsrLegacyMode_)
|
||||
if (!txUseBufferedIsr_)
|
||||
{
|
||||
const uint32_t setW = (uint32_t)mask;
|
||||
const uint32_t resetW = ((uint32_t)mask) << 16U;
|
||||
@ -850,33 +938,49 @@ void IR_Encoder::_isr()
|
||||
{
|
||||
port->BSRR = resetW;
|
||||
isSending = false;
|
||||
txUseBufferedIsr_ = false;
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
refreshBlindDecoderMuteState();
|
||||
carrierStopPending = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
port->BSRR = txBsrrWords_[txBsrrReadIdx_];
|
||||
txBsrrReadIdx_++;
|
||||
txBsrrTicksSent_++;
|
||||
|
||||
if (txBsrrTicksSent_ >= txBsrrTotalTicks_)
|
||||
IrTxIsrBufferedStorageBase* buf = txActiveBufferedCtx_;
|
||||
if (buf == nullptr || !buf->isValid())
|
||||
{
|
||||
port->BSRR = ((uint32_t)mask) << 16U;
|
||||
isSending = false;
|
||||
txUseBufferedIsr_ = false;
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
refreshBlindDecoderMuteState();
|
||||
carrierStopPending = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (txBsrrReadIdx_ == txBsrrHalfLen_)
|
||||
port->BSRR = buf->bsrrWords[buf->readIdx];
|
||||
buf->readIdx++;
|
||||
buf->ticksSent++;
|
||||
|
||||
if (buf->ticksSent >= buf->totalTicks)
|
||||
{
|
||||
txBsrrWave_.fill(&txBsrrWords_[0], txBsrrHalfLen_);
|
||||
port->BSRR = ((uint32_t)mask) << 16U;
|
||||
isSending = false;
|
||||
txUseBufferedIsr_ = false;
|
||||
txActiveBufferedCtx_ = nullptr;
|
||||
refreshBlindDecoderMuteState();
|
||||
carrierStopPending = true;
|
||||
return;
|
||||
}
|
||||
else if (txBsrrReadIdx_ >= irproto::kIsrTxBsrrWordCount)
|
||||
|
||||
if (buf->readIdx == buf->halfLen)
|
||||
{
|
||||
txBsrrReadIdx_ = 0;
|
||||
txBsrrWave_.fill(&txBsrrWords_[txBsrrHalfLen_], txBsrrHalfLen_);
|
||||
buf->wave.fill(&buf->bsrrWords[0], buf->halfLen);
|
||||
}
|
||||
else if (buf->readIdx >= buf->wordCount)
|
||||
{
|
||||
buf->readIdx = 0;
|
||||
buf->wave.fill(&buf->bsrrWords[buf->halfLen], buf->halfLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user