mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-09-22 12:59:36 +00:00
archive: freeze IR-protocol WIP before stepwise integration
This commit is contained in:
@ -120,7 +120,23 @@ public:
|
||||
if (enc == nullptr) return IR_SendStatus::ExternalNoStream;
|
||||
for (uint8_t i = 0; i < streamCount_; i++) {
|
||||
if (streams_[i].enc == enc) {
|
||||
return startStream(streams_[i], packet, len);
|
||||
const IR_TxSnapshot snapshot = enc->txSnapshot();
|
||||
const IR_TxPlan plan = enc->planTransmission(packet, len);
|
||||
return startStream(streams_[i], packet, len, plan, snapshot.operationId);
|
||||
}
|
||||
}
|
||||
return IR_SendStatus::ExternalNoStream;
|
||||
}
|
||||
|
||||
IR_SendStatus startTracked(IR_Encoder* enc,
|
||||
const uint8_t* packet,
|
||||
uint8_t len,
|
||||
const IR_TxPlan& plan,
|
||||
uint32_t operationId) {
|
||||
if (enc == nullptr) return IR_SendStatus::ExternalNoStream;
|
||||
for (uint8_t i = 0; i < streamCount_; i++) {
|
||||
if (streams_[i].enc == enc) {
|
||||
return startStream(streams_[i], packet, len, plan, operationId);
|
||||
}
|
||||
}
|
||||
return IR_SendStatus::ExternalNoStream;
|
||||
@ -192,6 +208,7 @@ private:
|
||||
|
||||
uint32_t totalTicks = 0;
|
||||
volatile uint32_t ticksOutput = 0;
|
||||
uint32_t operationId = 0;
|
||||
|
||||
// Fix D (watchdog): прогресс ticksOutput против стенных часов (контекст потока).
|
||||
uint32_t lastTicks = 0;
|
||||
@ -204,20 +221,23 @@ private:
|
||||
ticksOutput = 0;
|
||||
totalTicks = 0;
|
||||
runCount = 0;
|
||||
operationId = 0;
|
||||
}
|
||||
|
||||
IR_DMA_TX_HOT void fill(uint32_t* dst, uint16_t count) {
|
||||
wave.fill(dst, count);
|
||||
}
|
||||
|
||||
void onHalf() {
|
||||
void advanceHalf() {
|
||||
ticksOutput += halfLen;
|
||||
}
|
||||
|
||||
void refillFirstHalf() {
|
||||
fill(&dmaBuf[0], halfLen);
|
||||
__DSB(); // Fix #8: refill первой половины виден DMA до следующего прохода кольца
|
||||
}
|
||||
|
||||
void onComplete() {
|
||||
ticksOutput += halfLen;
|
||||
void refillSecondHalf() {
|
||||
fill(&dmaBuf[halfLen], halfLen);
|
||||
__DSB(); // Fix #8: refill второй половины виден DMA до следующего прохода кольца
|
||||
}
|
||||
@ -262,7 +282,7 @@ private:
|
||||
void forceStop(TxStream& s) {
|
||||
HAL_NVIC_DisableIRQ(s.dmaIrq);
|
||||
if (s.active) {
|
||||
stopStream(s);
|
||||
stopStream(s, IR_SendStatus::DmaStalled);
|
||||
recoveries_++;
|
||||
}
|
||||
HAL_NVIC_EnableIRQ(s.dmaIrq);
|
||||
@ -281,18 +301,22 @@ private:
|
||||
static void dmaHalfCpltCb(DMA_HandleTypeDef* hdma) {
|
||||
auto* s = streamFromDma(hdma);
|
||||
if (s == nullptr || !s->active) return;
|
||||
s->onHalf();
|
||||
s->advanceHalf();
|
||||
if (s_instance != nullptr && s->ticksOutput >= s->totalTicks) {
|
||||
s_instance->stopStream(*s);
|
||||
s_instance->stopStream(*s, IR_SendStatus::Success);
|
||||
} else {
|
||||
s->refillFirstHalf();
|
||||
}
|
||||
}
|
||||
|
||||
static void dmaCpltCb(DMA_HandleTypeDef* hdma) {
|
||||
auto* s = streamFromDma(hdma);
|
||||
if (s == nullptr || !s->active) return;
|
||||
s->onComplete();
|
||||
s->advanceHalf();
|
||||
if (s_instance != nullptr && s->ticksOutput >= s->totalTicks) {
|
||||
s_instance->stopStream(*s);
|
||||
s_instance->stopStream(*s, IR_SendStatus::Success);
|
||||
} else {
|
||||
s->refillSecondHalf();
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,7 +326,7 @@ private:
|
||||
s->onError();
|
||||
if (s_instance != nullptr) {
|
||||
s_instance->errors_++; // Fix #5: наблюдаемость аварийных завершений по Transfer-Error
|
||||
s_instance->stopStream(*s);
|
||||
s_instance->stopStream(*s, IR_SendStatus::DmaTransferError);
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,21 +372,29 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
IR_SendStatus startStream(TxStream& s, const uint8_t* packet, uint8_t len) {
|
||||
IR_SendStatus startStream(TxStream& s,
|
||||
const uint8_t* packet,
|
||||
uint8_t len,
|
||||
const IR_TxPlan& expectedPlan,
|
||||
uint32_t operationId) {
|
||||
if (s.enc == nullptr || s.port == nullptr || s.mask == 0) return IR_SendStatus::ExternalInvalidConfig;
|
||||
if (s.active) return IR_SendStatus::EncoderBusy;
|
||||
if (!expectedPlan.valid() || operationId == 0U) return IR_SendStatus::ExternalInvalidConfig;
|
||||
if (s.dmaBuf == nullptr || s.bufLen < 2 || s.halfLen == 0) return IR_SendStatus::ExternalInvalidConfig;
|
||||
if (s.runs == nullptr || s.maxRuns == 0) return IR_SendStatus::ExternalInvalidConfig;
|
||||
|
||||
s.resetWave();
|
||||
|
||||
const uint16_t mult = IR_Encoder::carrierMultiply();
|
||||
s.runCount = IR_Encoder::buildPhysicalGateRuns(packet, len, s.runs, s.maxRuns, mult);
|
||||
if (s.runCount == 0) return IR_SendStatus::BuildGateRunsFailed;
|
||||
|
||||
uint32_t total = 0;
|
||||
for (size_t i = 0; i < s.runCount; i++) total += s.runs[i].lenTicks;
|
||||
s.totalTicks = total;
|
||||
const uint16_t mult = expectedPlan.carrierMultiply;
|
||||
const IR_TxPlan built = IR_Encoder::buildPhysicalTransmission(
|
||||
packet, len, s.runs, s.maxRuns, mult);
|
||||
if (!built.valid()) return built.status;
|
||||
if (built.physicalTicks != expectedPlan.physicalTicks ||
|
||||
built.gateRunCount != expectedPlan.gateRunCount)
|
||||
return IR_SendStatus::PlanMismatch;
|
||||
s.runCount = static_cast<size_t>(built.gateRunCount);
|
||||
s.totalTicks = built.physicalTicks;
|
||||
s.operationId = operationId;
|
||||
|
||||
uint16_t pwr = mult / 2U;
|
||||
if (s.enc != nullptr) {
|
||||
@ -388,6 +420,7 @@ private:
|
||||
const uint32_t dst = u32ptr(&s.port->BSRR);
|
||||
if (HAL_DMA_Start_IT(&s.hdma, (uint32_t)(uintptr_t)s.dmaBuf, dst, s.bufLen) != HAL_OK) {
|
||||
s.active = false;
|
||||
s.operationId = 0U;
|
||||
return IR_SendStatus::DmaStartFailed;
|
||||
}
|
||||
|
||||
@ -395,10 +428,12 @@ private:
|
||||
return IR_SendStatus::Success;
|
||||
}
|
||||
|
||||
void stopStream(TxStream& s) {
|
||||
void stopStream(TxStream& s, IR_SendStatus terminalStatus) {
|
||||
if (!s.active) return;
|
||||
|
||||
const uint32_t operationId = s.operationId;
|
||||
s.active = false;
|
||||
s.operationId = 0U;
|
||||
HAL_DMA_Abort_IT(&s.hdma);
|
||||
|
||||
if (s.port != nullptr) {
|
||||
@ -406,7 +441,7 @@ private:
|
||||
}
|
||||
|
||||
if (s.enc != nullptr) {
|
||||
s.enc->externalFinishSend();
|
||||
s.enc->externalFinishSend(operationId, terminalStatus);
|
||||
}
|
||||
// Fix C: TIM НЕ останавливаем — он free-running, без разделяемого счётчика.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user