mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-03-13 04:44:44 +00:00
upd
This commit is contained in:
184
IR_Encoder.cpp
184
IR_Encoder.cpp
@ -1,5 +1,6 @@
|
||||
#include "IR_Encoder.h"
|
||||
#include "IR_DecoderRaw.h"
|
||||
#include <string.h>
|
||||
|
||||
#define LoopOut 12
|
||||
#define ISR_Out 10
|
||||
@ -45,6 +46,9 @@ IR_Encoder::IR_Encoder(uint8_t pin, uint16_t addr, IR_DecoderRaw *decPair, bool
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
inline HardwareTimer* IR_Encoder::get_IR_Timer(){return IR_Encoder::IR_Timer;}
|
||||
|
||||
@ -78,6 +82,164 @@ void IR_Encoder::begin(HardwareTimer* timer, uint8_t channel, IRQn_Type IRQn, ui
|
||||
IR_Timer->pause();
|
||||
}
|
||||
|
||||
void IR_Encoder::beginClockOnly(HardwareTimer *timer)
|
||||
{
|
||||
IR_Timer = timer;
|
||||
if (IR_Timer == nullptr)
|
||||
return;
|
||||
IR_Timer->pause();
|
||||
IR_Timer->setOverflow(carrierFrec * 2, HERTZ_FORMAT);
|
||||
IR_Timer->pause();
|
||||
}
|
||||
|
||||
void IR_Encoder::setExternalTxBackend(ExternalTxStartFn startFn, ExternalTxBusyFn busyFn, void *ctx)
|
||||
{
|
||||
externalTxStartFn = startFn;
|
||||
externalTxBusyFn = busyFn;
|
||||
externalTxCtx = ctx;
|
||||
}
|
||||
|
||||
void IR_Encoder::externalFinishSend()
|
||||
{
|
||||
if (!isSending)
|
||||
return;
|
||||
|
||||
// Force output low.
|
||||
if (port != nullptr) {
|
||||
port->BSRR = ((uint32_t)mask) << 16;
|
||||
}
|
||||
|
||||
isSending = false;
|
||||
setDecoder_isSending();
|
||||
}
|
||||
|
||||
size_t IR_Encoder::buildGateRuns(const uint8_t *packet, uint8_t len, IR_TxGateRun *outRuns, size_t maxRuns)
|
||||
{
|
||||
if (packet == nullptr || outRuns == nullptr || maxRuns == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (len == 0 || len > dataByteSizeMax)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copy into fixed-size buffer to match original encoder behavior (safe reads past sendLen).
|
||||
uint8_t sendBufferLocal[dataByteSizeMax] = {0};
|
||||
memcpy(sendBufferLocal, packet, len);
|
||||
|
||||
uint8_t sendLenLocal = len;
|
||||
uint8_t toggleCounterLocal = preambToggle;
|
||||
uint8_t dataBitCounterLocal = bitPerByte - 1;
|
||||
uint8_t dataByteCounterLocal = 0;
|
||||
uint8_t preambFrontCounterLocal = preambPulse * 2 - 1;
|
||||
uint8_t dataSequenceCounterLocal = bitPerByte * 2;
|
||||
uint8_t syncSequenceCounterLocal = syncBits * 2;
|
||||
bool syncLastBitLocal = false;
|
||||
SignalPart signalLocal = preamb;
|
||||
bool stateLocal = HIGH;
|
||||
uint8_t *currentBitSequenceLocal = bitHigh;
|
||||
|
||||
size_t runCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const bool gate = stateLocal;
|
||||
const uint16_t runLenTicks = (uint16_t)toggleCounterLocal + 1U;
|
||||
|
||||
if (runCount > 0 && outRuns[runCount - 1].gate == gate)
|
||||
{
|
||||
outRuns[runCount - 1].lenTicks = (uint16_t)(outRuns[runCount - 1].lenTicks + runLenTicks);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (runCount >= maxRuns)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
outRuns[runCount].gate = gate;
|
||||
outRuns[runCount].lenTicks = runLenTicks;
|
||||
runCount++;
|
||||
}
|
||||
|
||||
// Advance state to the next run boundary (equivalent to ISR iteration when toggleCounter == 0).
|
||||
while (true)
|
||||
{
|
||||
switch (signalLocal)
|
||||
{
|
||||
case noSignal:
|
||||
return runCount;
|
||||
|
||||
case preamb:
|
||||
if (preambFrontCounterLocal)
|
||||
{
|
||||
preambFrontCounterLocal--;
|
||||
toggleCounterLocal = preambToggle;
|
||||
break;
|
||||
}
|
||||
// End of preamble.
|
||||
signalLocal = data;
|
||||
stateLocal = !LOW;
|
||||
continue;
|
||||
|
||||
case data:
|
||||
if (dataSequenceCounterLocal)
|
||||
{
|
||||
if (!(dataSequenceCounterLocal & 1U))
|
||||
{
|
||||
currentBitSequenceLocal = ((sendBufferLocal[dataByteCounterLocal] >> dataBitCounterLocal) & 1U) ? bitHigh : bitLow;
|
||||
dataBitCounterLocal--;
|
||||
}
|
||||
toggleCounterLocal = currentBitSequenceLocal[!stateLocal];
|
||||
dataSequenceCounterLocal--;
|
||||
break;
|
||||
}
|
||||
// End of data byte.
|
||||
syncLastBitLocal = ((sendBufferLocal[dataByteCounterLocal]) & 1U);
|
||||
dataByteCounterLocal++;
|
||||
dataBitCounterLocal = bitPerByte - 1;
|
||||
dataSequenceCounterLocal = bitPerByte * 2;
|
||||
signalLocal = sync;
|
||||
continue;
|
||||
|
||||
case sync:
|
||||
if (syncSequenceCounterLocal)
|
||||
{
|
||||
if (!(syncSequenceCounterLocal & 1U))
|
||||
{
|
||||
if (syncSequenceCounterLocal == 2)
|
||||
{
|
||||
currentBitSequenceLocal = ((sendBufferLocal[dataByteCounterLocal]) & 0b10000000) ? bitLow : bitHigh;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentBitSequenceLocal = syncLastBitLocal ? bitLow : bitHigh;
|
||||
syncLastBitLocal = !syncLastBitLocal;
|
||||
}
|
||||
}
|
||||
toggleCounterLocal = currentBitSequenceLocal[!stateLocal];
|
||||
syncSequenceCounterLocal--;
|
||||
break;
|
||||
}
|
||||
// End of sync.
|
||||
signalLocal = data;
|
||||
syncSequenceCounterLocal = syncBits * 2;
|
||||
if (dataByteCounterLocal >= sendLenLocal)
|
||||
{
|
||||
signalLocal = noSignal;
|
||||
}
|
||||
continue;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
stateLocal = !stateLocal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IR_Encoder::enable()
|
||||
{
|
||||
@ -360,6 +522,27 @@ void IR_Encoder::rawSend(uint8_t *ptr, uint8_t len)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (externalTxStartFn != nullptr)
|
||||
{
|
||||
if (externalTxBusyFn != nullptr && externalTxBusyFn(externalTxCtx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark as sending and delegate actual signal output to external backend.
|
||||
setDecoder_isSending();
|
||||
sendLen = len;
|
||||
isSending = true;
|
||||
|
||||
const bool ok = externalTxStartFn(externalTxCtx, this, ptr, len);
|
||||
if (!ok)
|
||||
{
|
||||
isSending = false;
|
||||
setDecoder_isSending();
|
||||
}
|
||||
return;
|
||||
}
|
||||
IR_Encoder::carrierResume();
|
||||
// Serial.println("START");
|
||||
setDecoder_isSending();
|
||||
@ -380,7 +563,6 @@ void IR_Encoder::rawSend(uint8_t *ptr, uint8_t len)
|
||||
state = HIGH;
|
||||
|
||||
currentBitSequence = bitHigh;
|
||||
isSending = true;
|
||||
// interrupts();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user