check sync bits, fix rare invert error

This commit is contained in:
DashyFox 2024-01-25 14:33:59 +03:00
parent b05b9dc9d5
commit 6691915aa0
2 changed files with 179 additions and 138 deletions

View File

@ -7,57 +7,73 @@
) )
IR_Decoder::IR_Decoder(const uint8_t isrPin, uint16_t addr, IR_Encoder* encPair = nullptr) : isrPin(isrPin), addrSelf(addr), encoder(encPair) { IR_Decoder::IR_Decoder(const uint8_t isrPin, uint16_t addr, IR_Encoder* encPair = nullptr) : isrPin(isrPin), addrSelf(addr), encoder(encPair) {
rawBuffer = new uint8_t[bufferRawSize] { 0 }; // rawBuffer = new uint8_t[bufferRawSize] { 0 };
dataBuffer = rawBuffer; dataBuffer = new uint8_t[bufferDataSize] { 0 };
prevRise = prevFall = prevPrevFall = prevPrevRise = 0; prevRise = prevFall = prevPrevFall = prevPrevRise = 0;
start_RX(); start_RX();
} }
IR_Decoder::~IR_Decoder() { IR_Decoder::~IR_Decoder() {
delete rawBuffer; delete dataBuffer;
} }
void IR_Decoder::writeToBuffer(bool bit) { void IR_Decoder::writeToBuffer(bool bit) {
if (isBufferOverflow || isPreamb) return; if (i_dataBuffer >= bufferDataSize * 8 - 1) {// проверка переполнения
//TODO: Буффер переполнен!
isBufferOverflow = true;
}
if (isBufferOverflow || isPreamb || isWrongPack) return;
// Переключение флага, data или syncBit // Переключение флага, data или syncBit
if (bufBitPos == nextControlBit) { if (bufBitPos == nextControlBit) {
nextControlBit += (isData ? syncBits : bitPerByte); nextControlBit += (isData ? syncBits : bitPerByte); // маркер следующего переключения
isData = !isData; isData = !isData;
i_syncBit = 0; i_syncBit = 0; // сброс счетчика битов синхронизации
err_syncBit = 0; // сброс счетчика ошибок синхронизации
Serial.print(" "); Serial.print(" ");
} }
if (isData) { // Запись битов в dataBuffer if (isData) { // Запись битов в dataBuffer
Serial.print(bit);
if (i_dataBuffer % 8 == 7) { if (i_dataBuffer % 8 == 7) {
Serial.print("+"); // Serial.print("+");
} }
dataBuffer[(i_dataBuffer / 8)] |= bit << (7 - i_dataBuffer % 8); dataBuffer[(i_dataBuffer / 8)] |= bit << (7 - i_dataBuffer % 8);
i_dataBuffer++; i_dataBuffer++;
bufBitPos++; bufBitPos++;
} else { // Проверка контрольных sync битов } else {
//********************************* Проверка контрольных sync битов*******************************//
////////////////////// Исправление лишнего нуля ///////////////////////
if (i_syncBit == 0) { // Первый бит синхронизации if (i_syncBit == 0) { // Первый бит синхронизации
Serial.print("~"); // Serial.print("~");
if (bit != (dataBuffer[((i_dataBuffer - 1) / 8)] & 1 << (7 - (i_dataBuffer - 1) % 8) & 1)) { if (bit != (dataBuffer[((i_dataBuffer - 1) / 8)] >> (7 - (i_dataBuffer - 1) % 8) & 1)) {
bufBitPos++; bufBitPos++;
i_syncBit++; i_syncBit++;
} else { } else {
i_syncBit = 0; i_syncBit = 0;
errorCounter++; errorCounter++;
Serial.print("E"); // Serial.print("E");
err_syncBit++;
// Serial.print("bit: "); Serial.println(bit); // Serial.print("bit: "); Serial.println(bit);
// Serial.print("dataBuffer: "); Serial.println(dataBuffer[((i_dataBuffer - 1) / 8)] & 1 << (7 - ((i_dataBuffer - 1) & ~(~0 << 3)))); // Serial.print("dataBuffer: "); Serial.println(dataBuffer[((i_dataBuffer - 1) / 8)] & 1 << (7 - ((i_dataBuffer - 1) & ~(~0 << 3))));
} }
} else { // Последующие биты синхронизации } else { // Последующие биты синхронизации
Serial.print("`"); // Serial.print("`");
bufBitPos++; bufBitPos++;
i_syncBit++; i_syncBit++;
} }
} ////////////////////// Проверка наличия битов синхранизации //////////////////////
Serial.print(bit); isWrongPack = err_syncBit >= syncBits;
if (isWrongPack) Serial.print("****************");
}//**************************************************************************************************//
// Serial.print(bit);
#ifdef IRDEBUG
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
#endif
// if (bufBitPos >= bufferRawSize * 8 - 1) { isBufferOverflow = true; }
@ -78,14 +94,7 @@ void IR_Decoder::writeToBuffer(bool bit) {
/* /*
#ifdef IRDEBUG ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
#endif
if (isBufferOverflow) { //TODO: Буффер переполнен!
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//const auto testval = bufferBitSizeMax; //const auto testval = bufferBitSizeMax;
if ((bufBitPos >= (8 * msgBytes) - syncBits) && !isMsgAvaliable) { if ((bufBitPos >= (8 * msgBytes) - syncBits) && !isMsgAvaliable) {
switch ((rawBuffer[0] >> 5) & IR_MASK_MSG_TYPE) { switch ((rawBuffer[0] >> 5) & IR_MASK_MSG_TYPE) {
@ -138,42 +147,42 @@ void IR_Decoder::writeToBuffer(bool bit) {
} }
uint8_t* IR_Decoder::getDataBuffer(bool reset = false) { // uint8_t* IR_Decoder::getDataBuffer(bool reset = false) {
if (!isRawAvaliable) { return nullptr; } // if (!isRawAvaliable) { return nullptr; }
if (dataBuffer != nullptr) { delete dataBuffer; dataBuffer = nullptr; } // устранение утечки памяти // if (dataBuffer != nullptr) { delete dataBuffer; dataBuffer = nullptr; } // устранение утечки памяти
dataBuffer = new uint8_t[dataByteSizeMax] { 0 }; // Буффер по максимуму // dataBuffer = new uint8_t[dataByteSizeMax] { 0 }; // Буффер по максимуму
bool isData = true; // bool isData = true;
bool controlCheckFirst = true; // bool controlCheckFirst = true;
bool controlCheck; // bool controlCheck;
uint8_t nextControlBit = bitPerByte; // uint8_t nextControlBit = bitPerByte;
uint16_t i_dataBuffer = 0; // uint16_t i_dataBuffer = 0;
for (uint16_t i = 0; i < dataBitSize; i++) { // for (uint16_t i = 0; i < dataBitSize; i++) {
if (i == nextControlBit) { // if (i == nextControlBit) {
controlCheckFirst = true; // controlCheckFirst = true;
nextControlBit += (isData ? syncBits : bitPerByte); // nextControlBit += (isData ? syncBits : bitPerByte);
isData = !isData; // isData = !isData;
} // }
if (isData) { // if (isData) {
dataBuffer[i_dataBuffer / 8] |= (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1) << 7 - (i_dataBuffer % 8); // dataBuffer[i_dataBuffer / 8] |= (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1) << 7 - (i_dataBuffer % 8);
i_dataBuffer++; // i_dataBuffer++;
} else { // Проверка контрольных sync битов // } else { // Проверка контрольных sync битов
if (controlCheckFirst) { // if (controlCheckFirst) {
controlCheck = (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1); // controlCheck = (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1);
controlCheckFirst = false; // controlCheckFirst = false;
} else { // } else {
controlCheck |= (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1); // controlCheck |= (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1);
} // }
} // }
} // }
isFilterBufferAvaliable = controlCheck; // isFilterBufferAvaliable = controlCheck;
if (reset) { resetAvaliable(); } // if (reset) { resetAvaliable(); }
return dataBuffer; // return dataBuffer;
} // }
bool IR_Decoder::crcCheck(uint8_t len) { bool IR_Decoder::crcCheck(uint8_t len) {
bool crcOK = false; bool crcOK = false;
@ -208,13 +217,14 @@ void IR_Decoder::start_RX() {
resetAvaliable(); resetAvaliable();
isBufferOverflow = false; isBufferOverflow = false;
memset(rawBuffer, 0x00, bufferRawSize); memset(dataBuffer, 0x00, bufferDataSize);
bufBitPos = 0; bufBitPos = 0;
isData = true; isData = true;
i_dataBuffer = 0; i_dataBuffer = 0;
nextControlBit = bitPerByte; nextControlBit = bitPerByte;
i_syncBit = 0; i_syncBit = 0;
isWrongPack = false;
} }
void IR_Decoder::resetAvaliable() { void IR_Decoder::resetAvaliable() {
@ -250,13 +260,19 @@ void IR_Decoder::tick() {
interrupts(); interrupts();
//////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (currentFront.time - prevRise > IR_timeout && currentFront.dir) { // первый ↑ if (currentFront.time - prevRise > IR_timeout) { // первый
// if (!currentFront.dir) { // ↓
errorCounter = 0;
isRecive = true; isRecive = true;
isPreamb = true; isPreamb = true;
frontCounter = preambFronts - 1U; // frontCounter = preambFronts - 1U;
errorCounter = 0; // } else { // ↑
riseSyncTime = bitTime /* 1100 */; riseSyncTime = bitTime /* 1100 */;
start_RX(); start_RX();
frontCounter = preambFronts - 1U;
// }
// Serial.println(); // Serial.println();
// Serial.print("currentFront.time: "); Serial.println(currentFront.time); // Serial.print("currentFront.time: "); Serial.println(currentFront.time);
@ -286,7 +302,6 @@ void IR_Decoder::tick() {
} }
isPreamb = false; isPreamb = false;
} }
// определить направление фронта // определить направление фронта
if (currentFront.dir) { // Если __/``` ↑ if (currentFront.dir) { // Если __/``` ↑
@ -297,8 +312,10 @@ void IR_Decoder::tick() {
int8_t highCount = 0; int8_t highCount = 0;
int8_t lowCount = 0; int8_t lowCount = 0;
int8_t allCount = 0; int8_t allCount = 0;
bool invertErr = false;
if (risePeriod < IR_timeout && !isBufferOverflow && risePeriod > riseTimeMin) {
if (risePeriod < IR_timeout && !isBufferOverflow && risePeriod > riseTimeMin && !isWrongPack) {
// Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц // Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц
if (aroundRise(risePeriod)) { // тактирование есть, сигнал хороший - без ошибок(?) if (aroundRise(risePeriod)) { // тактирование есть, сигнал хороший - без ошибок(?)
@ -339,7 +356,13 @@ void IR_Decoder::tick() {
#ifdef IRDEBUG #ifdef IRDEBUG
errPulse(errOut, 4); errPulse(errOut, 4);
#endif #endif
} else if (lowCount == highCount) {} // неизвестный случай // неизвестный случай Инверсит след бит или соседние
// Очень редко
// TODO: Отловить проверить
} else if (lowCount == highCount) {
invertErr = true;
Serial.print("...");
}
errorCounter += allCount; errorCounter += allCount;
} }
@ -349,19 +372,35 @@ void IR_Decoder::tick() {
#endif #endif
for (int8_t i = 0; i < lowCount && 8 - i; i++) { // отправка LOW битов, если есть for (int8_t i = 0; i < lowCount && 8 - i; i++) { // отправка LOW битов, если есть
if (i == lowCount - 1 && invertErr) {
invertErr = false;
writeToBuffer(!LOW);
#ifdef IRDEBUG
digitalWrite(wrLow, 1);
#endif
} else {
writeToBuffer(LOW); writeToBuffer(LOW);
#ifdef IRDEBUG #ifdef IRDEBUG
digitalWrite(wrLow, 1); digitalWrite(wrLow, 1);
#endif #endif
} }
}
for (int8_t i = 0; i < highCount && 8 - i; i++) { // отправка HIGH битов, если есть for (int8_t i = 0; i < highCount && 8 - i; i++) { // отправка HIGH битов, если есть
if (i == highCount - 1 && invertErr) {
invertErr = false;
writeToBuffer(!HIGH);
#ifdef IRDEBUG
digitalWrite(wrLow, 1);
#endif
} else {
writeToBuffer(HIGH); writeToBuffer(HIGH);
#ifdef IRDEBUG #ifdef IRDEBUG
digitalWrite(wrHigh, 1); digitalWrite(wrHigh, 1);
#endif #endif
} }
} }
}
#ifdef IRDEBUG #ifdef IRDEBUG
digitalWrite(wrHigh, 0); digitalWrite(wrHigh, 0);
digitalWrite(wrLow, 0); digitalWrite(wrLow, 0);
@ -427,7 +466,7 @@ void IR_Decoder::isr() { // в прерывании вызываем isr()
} }
currentSubBufferIndex == (subBufferSize - 1) ? currentSubBufferIndex = 0 : currentSubBufferIndex++; currentSubBufferIndex == (subBufferSize - 1) ? currentSubBufferIndex = 0 : currentSubBufferIndex++; // Закольцовка буффера
} }

View File

@ -19,7 +19,7 @@
#define riseTimeMax (riseTime + riseTolerance) #define riseTimeMax (riseTime + riseTolerance)
#define riseTimeMin (riseTime - riseTolerance) #define riseTimeMin (riseTime - riseTolerance)
#define aroundRise(t) (riseTimeMin < t && t < riseTimeMax) #define aroundRise(t) (riseTimeMin < t && t < riseTimeMax)
#define IR_timeout ((riseTimeMax * 8) + syncBits +1) // us // таймаут в 8 data + 3 sync + 1 #define IR_timeout (riseTimeMax * (8 + syncBits +1)) // us // таймаут в 8 data + 3 sync + 1
#define subBufferSize 5 //Буфер для складирования фронтов, пока их не обработают #define subBufferSize 5 //Буфер для складирования фронтов, пока их не обработают
@ -188,15 +188,16 @@ private:
volatile bool isFilterBufferAvaliable = false; volatile bool isFilterBufferAvaliable = false;
volatile bool isBufferOverflow = false; volatile bool isBufferOverflow = false;
bool isWrongPack = false;
volatile bool isPreamb = false; // флаг начальной последовости volatile bool isPreamb = false; // флаг начальной последовости
bool HIGH_FIRST = true; // порядок приходящих битов bool HIGH_FIRST = true; // порядок приходящих битов
//Буффер //Буффер
const uint8_t bufferRawSize = // const uint8_t bufferRawSize =
((bufferBitSizeMax % 8 > 0) ? // ((bufferBitSizeMax % 8 > 0) ?
(bufferBitSizeMax / 8) + 1 : // (bufferBitSizeMax / 8) + 1 :
(bufferBitSizeMax / 8)); // (bufferBitSizeMax / 8));
const uint8_t bufferDataSize = dataByteSizeMax; // + crc const uint8_t bufferDataSize = dataByteSizeMax; // + crc
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
void noFunc(); void noFunc();
@ -220,7 +221,7 @@ private:
volatile FrontStorage* firstUnHandledFront = nullptr; // Указатель первого необработанного фронта/спада volatile FrontStorage* firstUnHandledFront = nullptr; // Указатель первого необработанного фронта/спада
volatile FrontStorage subBuffer[subBufferSize]; // вспомогательный буфер для хранения необработанных фронтов/спадов volatile FrontStorage subBuffer[subBufferSize]; // вспомогательный буфер для хранения необработанных фронтов/спадов
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
uint8_t* rawBuffer = nullptr; // uint8_t* rawBuffer = nullptr;
uint8_t* dataBuffer = nullptr; uint8_t* dataBuffer = nullptr;
volatile uint32_t prevRise, prevFall, prevPrevFall, prevPrevRise; volatile uint32_t prevRise, prevFall, prevPrevFall, prevPrevRise;
@ -236,6 +237,7 @@ private:
uint16_t i_dataBuffer; // Счётчик буфера данных uint16_t i_dataBuffer; // Счётчик буфера данных
uint8_t nextControlBit = bitPerByte; // Метка для смены флага isData uint8_t nextControlBit = bitPerByte; // Метка для смены флага isData
uint8_t i_syncBit; // Счётчик битов синхронизации uint8_t i_syncBit; // Счётчик битов синхронизации
uint8_t err_syncBit; // Счётчик ошибок синхронизации
void writeToBuffer(bool); void writeToBuffer(bool);
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
void start_RX(); void start_RX();