dma fix priority and debug

This commit is contained in:
2026-04-02 17:25:10 +03:00
parent af3e012aac
commit e7d7c0e1c1
18 changed files with 89260 additions and 142 deletions

View File

@ -1,5 +1,6 @@
#include "IR_DecoderRaw.h"
#include "IR_Encoder.h"
#include <cstdio>
#include <cstring>
IR_DecoderRaw::IR_DecoderRaw(const uint8_t pin, uint16_t addr, IR_Encoder *encPair) : encoder(encPair)
@ -48,29 +49,11 @@ volatile uint32_t time_;
void IR_DecoderRaw::isr()
{
// Serial.print("ISR\n");
if(isPairSending){
return;
}
noInterrupts();
// time_ = HAL_GetTick() * 1000 + ((SysTick->LOAD + 1 - SysTick->VAL) * 1000) / SysTick->LOAD + 1;
time_ = micros();
interrupts();
if (time_ < oldTime)
{
#ifdef IRDEBUG
Serial.print("\n");
Serial.print("count: ");
Serial.println(wrongCounter++);
Serial.print("time: ");
Serial.println(time_);
Serial.print("oldTime: ");
Serial.println(oldTime);
Serial.print("sub: ");
Serial.println(max((uint32_t)time_, oldTime) - min((uint32_t)time_, oldTime));
#endif
time_ += 1000;
}
oldTime = time_;
@ -79,6 +62,16 @@ void IR_DecoderRaw::isr()
edge.dir = port->IDR & mask;
edge.time = time_;
#if defined(IR_EDGE_TRACE)
edgeTracePush(edge.time, edge.dir ? 1u : 0u,
isPairSending ? (uint8_t)IR_EDGE_TRACE_F_SKIP_DECODE : 0u);
#endif
if (isPairSending)
{
return;
}
subBuffer.push(edge);
}
@ -86,9 +79,8 @@ void IR_DecoderRaw::isr()
void IR_DecoderRaw::firstRX()
{
#ifdef IRDEBUG_INFO
Serial.print("\nRX>");
#if defined(IRDEBUG_SERIAL_PACK)
packTraceResetFrame();
#endif
errors.reset();
@ -115,7 +107,9 @@ void IR_DecoderRaw::listenStart()
{
if (isReciveRaw && ((micros() - prevRise) > IR_timeout * 2))
{
// Serial.print("\nlis>");
#if defined(IRDEBUG_SERIAL_PACK)
packTraceOnTimeoutOrAbort(true);
#endif
isReciveRaw = false;
firstRX();
}
@ -129,6 +123,9 @@ inline void IR_DecoderRaw::checkTimeout()
if (micros() - lastEdgeTime > IR_timeout * 2U)
{
#if defined(IRDEBUG_SERIAL_PACK)
packTraceOnTimeoutOrAbort(false);
#endif
isRecive = false; // приём завершён
msgTypeReceive = 0;
// firstRX(); // подготовка к новому пакету
@ -154,6 +151,9 @@ void IR_DecoderRaw::tick()
isSubBufferOverflow = false;
checkTimeout(); // <--- новое место проверки
interrupts();
#if defined(IR_EDGE_TRACE)
while (edgeTraceFlushChunk(Serial, 48) > 0) {}
#endif
return;
} // Если данных нет - ничего не делаем
currentFront = *currentFrontPtr;
@ -245,6 +245,10 @@ void IR_DecoderRaw::tick()
isRecive = true;
isReciveRaw = true;
isWrongPack = false;
#if defined(IRDEBUG_SERIAL_PACK)
packTraceResetFrame();
packTraceOpen = true;
#endif
}
//-------------------------------------------------------------------------------------------------------
@ -252,8 +256,8 @@ void IR_DecoderRaw::tick()
if (preambFrontCounter)
{ // в преамбуле
#ifdef IRDEBUG
Serial.print("risePeriod: ");
Serial.println(risePeriod);
// Serial.print("risePeriod: ");
// Serial.println(risePeriod);
#endif
if (currentFront.dir && risePeriod < IR_timeout)
{ // __/``` ↑ и мы в внутри пакета
@ -313,21 +317,21 @@ void IR_DecoderRaw::tick()
lowCount = 0;
allCount = 0;
bool invertErr = false;
#ifdef IRDEBUG
Serial.print("\n");
// #ifdef IRDEBUG
// Serial.print("\n");
Serial.print("wrCounter: ");
Serial.println(wrCounter++);
// Serial.print("wrCounter: ");
// Serial.println(wrCounter++);
Serial.print("risePeriod: ");
Serial.println(risePeriod);
// Serial.print("risePeriod: ");
// Serial.println(risePeriod);
Serial.print("highTime: ");
Serial.println(highTime);
// Serial.print("highTime: ");
// Serial.println(highTime);
Serial.print("lowTime: ");
Serial.println(lowTime);
#endif
// Serial.print("lowTime: ");
// Serial.println(lowTime);
// #endif
if (aroundRise(risePeriod))
{ // тактирование есть, сигнал хороший - без ошибок(?)
@ -421,7 +425,7 @@ void IR_DecoderRaw::tick()
if (i == lowCount - 1 && invertErr)
{
invertErr = false;
writeToBuffer(HIGH);
writeToBuffer(HIGH, true);
#ifdef IRDEBUG
errPulse(wrHigh, 1);
#endif
@ -440,7 +444,7 @@ void IR_DecoderRaw::tick()
if (i == highCount - 1 && invertErr)
{
invertErr = false;
writeToBuffer(LOW);
writeToBuffer(LOW, true);
#ifdef IRDEBUG
errPulse(wrLow, 1);
#endif
@ -461,17 +465,23 @@ void IR_DecoderRaw::tick()
////////////////////////////////////////////////////////////////////////////////////////////////////////////
END:;
#if defined(IR_EDGE_TRACE)
while (edgeTraceFlushChunk(Serial, 48) > 0) {}
#endif
}
void IR_DecoderRaw::writeToBuffer(bool bit)
void IR_DecoderRaw::writeToBuffer(bool bit, bool packTraceInvertFix)
{
#if !defined(IRDEBUG_SERIAL_PACK)
(void)packTraceInvertFix;
#endif
if (i_dataBuffer > dataByteSizeMax * 8)
{ // проверка переполнения
// TODO: Буффер переполнен!
#ifdef IRDEBUG_INFO
Serial.println("OverBuf");
#endif
isBufferOverflow = true;
#if defined(IRDEBUG_SERIAL_PACK)
if (packTraceOpen)
packTraceEmitErrorFlash(F("ERROR: buffer overflow"));
#endif
}
if (isBufferOverflow || isPreamb || isWrongPack)
{
@ -488,104 +498,86 @@ void IR_DecoderRaw::writeToBuffer(bool bit)
isData = !isData;
i_syncBit = 0; // сброс счетчика битов синхронизации
err_syncBit = 0; // сброс счетчика ошибок синхронизации
#ifdef IRDEBUG_INFO
Serial.print(" ");
#endif
}
if (isData)
{ // Запись битов в dataBuffer
#ifdef IRDEBUG_INFO
Serial.print(bit);
#endif
// if (i_dataBuffer % 8 == 7) {
// // Serial.print("+");
// }
dataBuffer[(i_dataBuffer / 8)] |= bit << (7 - i_dataBuffer % 8); // Запись в буффер
i_dataBuffer++;
bufBitPos++;
#if defined(IRDEBUG_SERIAL_PACK)
if (packTraceInvertFix)
{
packTracePushChar('`');
packTracePushChar(bit ? '1' : '0');
packTracePushChar('`');
}
else
packTracePushBit(bit);
#endif
}
else
{
//********************************* Проверка контрольных sync битов*******************************//
//********************************* Проверка контрольных sync битов *******************************//
////////////////////// Исправление лишнего нуля ///////////////////////
if (i_syncBit == 0)
{ // Первый бит синхронизации
// Serial.print("~");
if (bit != (dataBuffer[((i_dataBuffer - 1) / 8)] >> (7 - (i_dataBuffer - 1) % 8) & 1))
{
bufBitPos++;
i_syncBit++;
#if defined(IRDEBUG_SERIAL_PACK)
packTracePushBit(bit);
#endif
}
else
{
i_syncBit = 0;
errors.other++;
// Serial.print("E");
err_syncBit++;
// Serial.print("bit: "); Serial.println(bit);
// Serial.print("dataBuffer: "); Serial.println(dataBuffer[((i_dataBuffer - 1) / 8)] & 1 << (7 - ((i_dataBuffer - 1) & ~(~0 << 3))));
const bool fatalSync = (err_syncBit >= syncBits);
if (fatalSync)
{
#if defined(IRDEBUG_SERIAL_PACK) && defined(IRDEBUG_SERIAL_SOFT_REJECT)
if (packTraceSoftReject())
{
packTraceHadWrongSync = true;
packTraceForceEndSyncPhase();
err_syncBit = 0;
i_syncBit = 0;
isWrongPack = false;
}
else
#endif
{
isWrongPack = true;
#if defined(IRDEBUG_SERIAL_PACK)
packTraceEmitErrorFlash(F("ERROR: Wrong sync bit"));
#endif
}
}
}
}
else
{ // Последующие биты синхронизации
// Serial.print("`");
bufBitPos++;
i_syncBit++;
}
////////////////////// Проверка наличия битов синхранизации //////////////////////
if (isWrongPack = (err_syncBit >= syncBits))
{
#ifdef IRDEBUG_INFO
Serial.print("****************");
#if defined(IRDEBUG_SERIAL_PACK)
packTracePushBit(bit);
#endif
};
}
isWrongPack = (err_syncBit >= syncBits);
} //**************************************************************************************************//
// Serial.print(bit);
#ifdef IRDEBUG
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef IRDEBUG_INFO
if (isData)
{
if (i_dataBuffer == ((msgBytes)*bitPerByte))
{
Serial.print(" -> ");
Serial.print(dataBuffer[0] & IR_MASK_MSG_INFO);
Serial.print(" ->");
}
if (i_dataBuffer == ((msgBytes + addrBytes) * bitPerByte))
{
Serial.print(" |");
}
if (i_dataBuffer == ((msgBytes + addrBytes + addrBytes) * bitPerByte))
{
Serial.print(" ->");
}
if (i_dataBuffer == (((dataBuffer[0] & IR_MASK_MSG_INFO) - 2) * bitPerByte))
{
Serial.print(" <-");
}
}
#endif
if (!isAvailable && isData && !isWrongPack)
{
if (i_dataBuffer == 8 * msgBytes)
{ // Ппервый байт
packSize = dataBuffer[0] & IR_MASK_MSG_INFO;
#ifdef IRDEBUG_INFO
Serial.print(" [");
Serial.print(packSize);
Serial.print("] ");
#endif
}
// Тип приёма (для isReceive): выставляем сразу после первого байта, ДО проверки «Конец».
@ -594,15 +586,10 @@ void IR_DecoderRaw::writeToBuffer(bool bit)
if (packSize && (i_dataBuffer == 8))
{
msgTypeReceive = (dataBuffer[0] >> 5) | 0b11111000;
// SerialUSB.println(msgTypeReceive & IR_MASK_MSG_TYPE);
}
if (packSize && (i_dataBuffer == packSize * bitPerByte))
{ // Конец
#ifdef IRDEBUG_INFO
Serial.print(" END DATA " + crcCheck(packSize - crcBytes, crcValue) ? "OK " : "ERR ");
#endif
packInfo.buffer = dataBuffer;
packInfo.crc = crcValue;
packInfo.err = errors;
@ -615,31 +602,47 @@ void IR_DecoderRaw::writeToBuffer(bool bit)
isAvailable = crcCheck(packSize - crcBytes, crcValue);
#ifdef BRUTEFORCE_CHECK
if (!isAvailable) // Исправление первого бита // Очень большая затычка...
for (size_t i = 0; i < min(uint16_t(packSize - crcBytes * 2U), uint16_t(dataByteSizeMax)); ++i)
{
for (int j = 0; j < 8; ++j)
{
uint16_t packTraceBfByte = 0;
uint8_t packTraceBfBit = 0;
bool packTraceBfMark = false;
if (!isAvailable) // Исправление первого бита // Очень большая затычка...
for (size_t i = 0; i < min(uint16_t(packSize - crcBytes * 2U), uint16_t(dataByteSizeMax)); ++i)
{
// инвертируем бит
dataBuffer[i] ^= 1 << j;
isAvailable = crcCheck(min(uint16_t(packSize - crcBytes), uint16_t(dataByteSizeMax - 1U)), crcValue);
// обратно инвертируем бит в исходное состояние
if (isAvailable)
{
#ifdef IRDEBUG_INFO
Serial.println("!!!INV!!!");
#endif
goto OUT_BRUTEFORCE;
}
else
for (int j = 0; j < 8; ++j)
{
// инвертируем бит
dataBuffer[i] ^= 1 << j;
isAvailable =
crcCheck(min(uint16_t(packSize - crcBytes), uint16_t(dataByteSizeMax - 1U)), crcValue);
// обратно инвертируем бит в исходное состояние
if (isAvailable)
{
packTraceBfByte = static_cast<uint16_t>(i);
packTraceBfBit = static_cast<uint8_t>(j);
packTraceBfMark = true;
goto OUT_BRUTEFORCE;
}
else
{
dataBuffer[i] ^= 1 << j;
}
}
}
}
OUT_BRUTEFORCE:;
OUT_BRUTEFORCE:
#if defined(IRDEBUG_SERIAL_PACK)
if (packTraceBfMark)
packTraceWrapDataBitInBackticks(packTraceBfByte, packTraceBfBit);
#endif
}
#endif
#if defined(IRDEBUG_SERIAL_PACK)
if (isAvailable)
packTraceEmitEndOk(static_cast<uint8_t>(packSize));
else
packTraceEmitEndBadCrc(static_cast<uint8_t>(packSize));
#endif
if (!isAvailable && packSize > 0 && packSize <= dataByteSizeMax) {
memcpy(rejectBuffer, dataBuffer, packSize);
@ -689,6 +692,461 @@ uint16_t IR_DecoderRaw::ceil_div(uint16_t val, uint16_t divider)
return ret;
}
#if defined(IR_EDGE_TRACE)
void IR_DecoderRaw::edgeTracePush(uint32_t t_us, uint8_t level, uint8_t flags)
{
const uint16_t cap = static_cast<uint16_t>(IR_EDGE_TRACE_CAPACITY);
noInterrupts();
const uint16_t w = edgeTrace_w;
const uint16_t r = edgeTrace_r;
const uint16_t next = static_cast<uint16_t>((w + 1u) % cap);
if (next == r)
{
edgeTrace_overflow = true;
interrupts();
return;
}
edgeTrace_buf[w].t_us = t_us;
edgeTrace_buf[w].level = level ? 1u : 0u;
edgeTrace_buf[w].flags = flags;
edgeTrace_w = next;
interrupts();
}
void IR_DecoderRaw::edgeTraceClear()
{
noInterrupts();
edgeTrace_w = 0;
edgeTrace_r = 0;
edgeTrace_overflow = false;
interrupts();
}
uint16_t IR_DecoderRaw::edgeTracePendingCount() const
{
noInterrupts();
const uint16_t w = edgeTrace_w;
const uint16_t r = edgeTrace_r;
interrupts();
const uint16_t cap = static_cast<uint16_t>(IR_EDGE_TRACE_CAPACITY);
if (w >= r)
return static_cast<uint16_t>(w - r);
return static_cast<uint16_t>(cap - r + w);
}
uint16_t IR_DecoderRaw::edgeTraceFlushChunk(Print &out, uint16_t maxRec)
{
if (maxRec == 0)
maxRec = 48;
constexpr uint16_t kStackCap = 64;
if (maxRec > kStackCap)
maxRec = kStackCap;
const uint16_t cap = static_cast<uint16_t>(IR_EDGE_TRACE_CAPACITY);
noInterrupts();
const uint16_t w = edgeTrace_w;
const uint16_t r = edgeTrace_r;
uint16_t avail = (w >= r) ? static_cast<uint16_t>(w - r) : static_cast<uint16_t>(cap - r + w);
uint16_t toCopy = (avail > maxRec) ? maxRec : avail;
const bool truncated = (avail > toCopy);
if (toCopy == 0)
{
interrupts();
return 0;
}
uint8_t tmp[kStackCap * 6];
for (uint16_t i = 0; i < toCopy; ++i)
{
const uint16_t idx = static_cast<uint16_t>((r + i) % cap);
memcpy(tmp + i * 6u, &edgeTrace_buf[idx], 6u);
}
edgeTrace_r = static_cast<uint16_t>((r + toCopy) % cap);
const bool ovf = edgeTrace_overflow;
interrupts();
uint8_t meta = 0;
if (ovf)
meta |= 0x01u;
if (truncated)
meta |= 0x02u;
uint8_t line[3 + kStackCap * 6];
line[0] = meta;
line[1] = static_cast<uint8_t>(toCopy & 0xFFu);
line[2] = static_cast<uint8_t>((toCopy >> 8) & 0xFFu);
memcpy(line + 3, tmp, toCopy * 6u);
out.print(F("\n@IRF1v1:"));
static const char hd[] = "0123456789abcdef";
const uint16_t lineLen = static_cast<uint16_t>(3u + toCopy * 6u);
for (uint16_t i = 0; i < lineLen; ++i)
{
const uint8_t b = line[i];
out.write(hd[b >> 4]);
out.write(hd[b & 0x0Fu]);
}
out.write('\n');
return toCopy;
}
#endif // IR_EDGE_TRACE
#if defined(IRDEBUG_SERIAL_PACK)
struct IrPackTraceSeg
{
uint8_t isSync;
uint8_t nbits; // число логических бит (данные) или символов синхры
uint8_t nchars; // сырых символов в b (данные: 8…24 из‑за `0`/`1`)
char b[24];
};
namespace {
void ptPrintHexU8(uint8_t v)
{
static const char hd[] = "0123456789ABCDEF";
Serial.print(hd[v >> 4]);
Serial.print(hd[v & 0x0Fu]);
}
/** Тройной пробел перед началом блока: msg→from, from→to, to→data, data→CRC. */
static bool ptRawLeadTriple(uint8_t byteIndex, uint8_t framePs)
{
if (byteIndex == 1 || byteIndex == 3)
return true;
if (framePs > 7 && byteIndex == 5)
return true;
if (framePs >= 7 && byteIndex == static_cast<uint8_t>(framePs - 2))
return true;
return false;
}
/** В IR raw: только 0/1 из flex-сегмента (без `), takeBits логических бит после skipLogical. */
static void ptEmitRawFlexSliceSerial(const char *s, uint8_t nbytes, uint8_t skipLogical, uint8_t takeBits)
{
size_t i = 0;
uint8_t logical = 0;
uint8_t emitted = 0;
while (i < nbytes && emitted < takeBits)
{
if (s[i] == '`' && i + 2u < nbytes && (s[i + 1] == '0' || s[i + 1] == '1') && s[i + 2] == '`')
{
if (logical >= skipLogical)
{
Serial.print(s[i + 1]);
++emitted;
}
i += 3;
++logical;
}
else if (s[i] == '0' || s[i] == '1')
{
if (logical >= skipLogical)
{
Serial.print(s[i]);
++emitted;
}
++i;
++logical;
}
else
break;
}
}
static bool ptTryConsumeFlexDataBit(const char *buf, uint16_t len, uint16_t &pos, IrPackTraceSeg &d)
{
if (pos + 2 < len && buf[pos] == '`' && (buf[pos + 1] == '0' || buf[pos + 1] == '1') && buf[pos + 2] == '`')
{
if (d.nchars + 3u > sizeof(d.b))
return false;
d.b[d.nchars++] = '`';
d.b[d.nchars++] = buf[pos + 1];
d.b[d.nchars++] = '`';
pos = static_cast<uint16_t>(pos + 3u);
return true;
}
if (pos < len && (buf[pos] == '0' || buf[pos] == '1'))
{
if (d.nchars + 1u > sizeof(d.b))
return false;
d.b[d.nchars++] = buf[pos++];
return true;
}
return false;
}
} // namespace
void IR_DecoderRaw::packTraceResetFrame()
{
packTraceOpen = false;
packTraceHadWrongSync = false;
packTraceLen = 0;
packTraceBitBuf[0] = '\0';
}
void IR_DecoderRaw::packTracePushChar(char c)
{
if (packTraceLen + 1u < kPackTraceBufCap)
{
packTraceBitBuf[packTraceLen++] = c;
packTraceBitBuf[packTraceLen] = '\0';
}
}
void IR_DecoderRaw::packTracePushBit(bool bit) { packTracePushChar(bit ? '1' : '0'); }
void IR_DecoderRaw::packTraceWrapDataBitInBackticks(uint16_t byteIndex, uint8_t bitInByte)
{
const uint32_t target = uint32_t(byteIndex) * 8u + bitInByte;
uint32_t dbit = 0;
uint16_t pos = 0;
bool inData = true;
uint16_t len = packTraceLen;
if (len >= kPackTraceBufCap)
len = kPackTraceBufCap - 1u;
while (pos < len)
{
if (inData)
{
uint8_t bitLen = 0;
if (pos + 2 < len && packTraceBitBuf[pos] == '`' && packTraceBitBuf[pos + 2] == '`' &&
(packTraceBitBuf[pos + 1] == '0' || packTraceBitBuf[pos + 1] == '1'))
bitLen = 3;
else if (packTraceBitBuf[pos] == '0' || packTraceBitBuf[pos] == '1')
bitLen = 1;
else
return;
if (dbit == target)
{
if (bitLen == 3)
return;
if (packTraceLen + 2u >= kPackTraceBufCap)
return;
const uint8_t finalBit =
static_cast<uint8_t>((dataBuffer[byteIndex] >> (7u - bitInByte)) & 1u);
const char ch = finalBit ? '1' : '0';
memmove(packTraceBitBuf + pos + 2, packTraceBitBuf + pos, packTraceLen - pos);
packTraceBitBuf[pos] = '`';
packTraceBitBuf[pos + 1] = ch;
packTraceBitBuf[pos + 2] = '`';
packTraceLen += 2;
if (packTraceLen < kPackTraceBufCap)
packTraceBitBuf[packTraceLen] = '\0';
return;
}
++dbit;
pos = static_cast<uint16_t>(pos + bitLen);
if ((dbit % 8u) == 0u)
inData = false;
}
else
{
uint8_t sc = 0;
while (pos < len && sc < syncBits)
{
const char c = packTraceBitBuf[pos];
if (c == '0' || c == '1' || c == '?')
{
++pos;
++sc;
}
else
break;
}
inData = true;
}
}
}
bool IR_DecoderRaw::packTraceSoftReject() const
{
#if defined(IRDEBUG_SERIAL_SOFT_REJECT)
return true;
#else
return false;
#endif
}
void IR_DecoderRaw::packTraceForceEndSyncPhase()
{
for (uint8_t i = 0; i < syncBits; i++)
packTracePushChar('?');
const uint8_t cycLen = bitPerByte + syncBits;
const uint16_t cyc = uint16_t(bufBitPos / cycLen);
bufBitPos = uint16_t((cyc + 1u) * cycLen);
if (bufBitPos == nextControlBit)
{
nextControlBit += (isData ? syncBits : bitPerByte);
isData = !isData;
i_syncBit = 0;
err_syncBit = 0;
}
}
void IR_DecoderRaw::packTraceEmitHex(uint8_t byteCount) const
{
Serial.print(F("IR hex:"));
for (uint8_t i = 0; i < byteCount && i < dataByteSizeMax; i++)
{
Serial.print(' ');
ptPrintHexU8(dataBuffer[i]);
}
Serial.println();
}
void IR_DecoderRaw::packTraceEmitRawBitsLine(bool endWithNewline) const
{
Serial.print(F("IR raw: "));
uint16_t len = packTraceLen;
if (len >= kPackTraceBufCap)
len = kPackTraceBufCap - 1u;
const char *buf = packTraceBitBuf;
uint16_t pos = 0;
uint8_t byteIndex = 0;
bool firstSeg = true;
const uint8_t framePs =
(i_dataBuffer >= 8) ? static_cast<uint8_t>(dataBuffer[0] & IR_MASK_MSG_INFO) : 0;
while (pos < len)
{
IrPackTraceSeg d{};
d.isSync = 0;
while (pos < len && d.nbits < 8)
{
const uint16_t posBefore = pos;
if (!ptTryConsumeFlexDataBit(buf, len, pos, d))
break;
if (pos == posBefore)
break;
++d.nbits;
}
if (!d.nbits)
break;
if (!firstSeg)
{
if (ptRawLeadTriple(byteIndex, framePs))
Serial.print(F(" "));
else
Serial.print(' ');
}
firstSeg = false;
if (d.nbits < 8)
{
ptEmitRawFlexSliceSerial(d.b, d.nchars, 0, d.nbits);
break;
}
if (byteIndex == 0u)
{
ptEmitRawFlexSliceSerial(d.b, d.nchars, 0, 3);
Serial.print(' ');
ptEmitRawFlexSliceSerial(d.b, d.nchars, 3, 5);
}
else
ptEmitRawFlexSliceSerial(d.b, d.nchars, 0, 8);
++byteIndex;
if (pos >= len)
break;
IrPackTraceSeg s{};
s.isSync = 1;
while (pos < len && s.nbits < syncBits)
{
const char c = buf[pos];
if (c != '0' && c != '1' && c != '?')
break;
if (s.nchars >= sizeof(s.b))
break;
s.b[s.nchars++] = c;
++s.nbits;
++pos;
}
if (s.nbits)
{
Serial.print(' ');
for (uint8_t i = 0; i < s.nbits; ++i)
Serial.print(s.b[i]);
}
}
if (endWithNewline)
Serial.println();
}
void IR_DecoderRaw::packTraceEmitErrorFlash(const __FlashStringHelper *msg)
{
Serial.println();
packTraceEmitRawBitsLine(false);
Serial.print(F(" => "));
Serial.println(msg);
{
uint16_t nb = i_dataBuffer / 8u;
if (nb > dataByteSizeMax)
nb = dataByteSizeMax;
packTraceEmitHex(static_cast<uint8_t>(nb));
}
packTraceResetFrame();
}
void IR_DecoderRaw::packTraceEmitEndOk(uint8_t packSize)
{
Serial.println();
packTraceEmitRawBitsLine(false);
Serial.print(F(" => OK: "));
irPackTracePrintOkCommand(dataBuffer, packSize);
Serial.println();
packTraceEmitHex(packSize);
packTraceResetFrame();
}
void IR_DecoderRaw::packTraceEmitEndBadCrc(uint8_t packSize)
{
Serial.println();
packTraceEmitRawBitsLine(false);
Serial.println(F(" => ERROR: Wrong CRC"));
packTraceEmitHex(packSize);
packTraceResetFrame();
}
void IR_DecoderRaw::packTraceOnTimeoutOrAbort(bool fromListenStart)
{
(void)fromListenStart;
if (!packTraceOpen)
return;
const uint16_t expected = (i_dataBuffer >= 8) ? uint16_t(dataBuffer[0] & IR_MASK_MSG_INFO) : 0;
uint16_t gotBytes = i_dataBuffer / 8;
if (gotBytes > dataByteSizeMax)
gotBytes = dataByteSizeMax;
Serial.println();
packTraceEmitRawBitsLine(false);
Serial.print(F(" => ERROR: TIMEOUT, rx_data_size = "));
Serial.print(expected);
Serial.print(F(", but only "));
Serial.print(gotBytes);
Serial.println(F(" bytes received"));
packTraceEmitHex(static_cast<uint8_t>(gotBytes));
packTraceResetFrame();
}
__attribute__((weak)) void irPackTracePrintOkCommand(const uint8_t *buf, uint8_t packSize)
{
(void)buf;
(void)packSize;
}
#endif // IRDEBUG_SERIAL_PACK
// IRDEBUG FUNC
#ifdef IRDEBUG
inline void IR_DecoderRaw::errPulse(uint8_t pin, uint8_t count)