From 6691915aa0cb759d4124b9f3b652a78768247480 Mon Sep 17 00:00:00 2001 From: DashyFox Date: Thu, 25 Jan 2024 14:33:59 +0300 Subject: [PATCH] check sync bits, fix rare invert error --- IR_Decoder.cpp | 303 ++++++++++++++++++++++++++++--------------------- IR_Decoder.h | 14 ++- 2 files changed, 179 insertions(+), 138 deletions(-) diff --git a/IR_Decoder.cpp b/IR_Decoder.cpp index 02f45d6..bfc6cbf 100644 --- a/IR_Decoder.cpp +++ b/IR_Decoder.cpp @@ -7,174 +7,183 @@ ) 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 }; - dataBuffer = rawBuffer; + // rawBuffer = new uint8_t[bufferRawSize] { 0 }; + dataBuffer = new uint8_t[bufferDataSize] { 0 }; prevRise = prevFall = prevPrevFall = prevPrevRise = 0; start_RX(); } IR_Decoder::~IR_Decoder() { - delete rawBuffer; + delete dataBuffer; } 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 if (bufBitPos == nextControlBit) { - nextControlBit += (isData ? syncBits : bitPerByte); + nextControlBit += (isData ? syncBits : bitPerByte); // маркер следующего переключения isData = !isData; - i_syncBit = 0; + i_syncBit = 0; // сброс счетчика битов синхронизации + err_syncBit = 0; // сброс счетчика ошибок синхронизации Serial.print(" "); } if (isData) { // Запись битов в dataBuffer + Serial.print(bit); + if (i_dataBuffer % 8 == 7) { - Serial.print("+"); + // Serial.print("+"); } dataBuffer[(i_dataBuffer / 8)] |= bit << (7 - i_dataBuffer % 8); i_dataBuffer++; bufBitPos++; - } else { // Проверка контрольных sync битов + } else { + //********************************* Проверка контрольных sync битов*******************************// + ////////////////////// Исправление лишнего нуля /////////////////////// if (i_syncBit == 0) { // Первый бит синхронизации - Serial.print("~"); - if (bit != (dataBuffer[((i_dataBuffer - 1) / 8)] & 1 << (7 - (i_dataBuffer - 1) % 8) & 1)) { + // Serial.print("~"); + if (bit != (dataBuffer[((i_dataBuffer - 1) / 8)] >> (7 - (i_dataBuffer - 1) % 8) & 1)) { bufBitPos++; i_syncBit++; } else { i_syncBit = 0; errorCounter++; - Serial.print("E"); + // 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)))); } } else { // Последующие биты синхронизации - Serial.print("`"); + // Serial.print("`"); bufBitPos++; i_syncBit++; } - } - Serial.print(bit); + ////////////////////// Проверка наличия битов синхранизации ////////////////////// + isWrongPack = err_syncBit >= syncBits; + if (isWrongPack) Serial.print("****************"); + }//**************************************************************************************************// - // if (bufBitPos >= bufferRawSize * 8 - 1) { isBufferOverflow = true; } - - - - - - - - - - - - - - - - - - - - /* + // Serial.print(bit); #ifdef IRDEBUG bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1); #endif - if (isBufferOverflow) { //TODO: Буффер переполнен! - } - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - //const auto testval = bufferBitSizeMax; - if ((bufBitPos >= (8 * msgBytes) - syncBits) && !isMsgAvaliable) { - switch ((rawBuffer[0] >> 5) & IR_MASK_MSG_TYPE) { - case IR_MSG_ACCEPT: - if (bufBitPos >= ((msgBytes + addrBytes + crcBytes) * (8 + 3)) - syncBits) { - const uint8_t dataSize = msgBytes + addrBytes; - isRawAvaliable = true; - isMsgAvaliable = crcCheck(dataSize); - if (isMsgAvaliable && checkAddr(1, 2)) { - gotAccept._set(dataBuffer, msgBytes + addrBytes + crcBytes, crcValue, errorCounter, riseSyncTime); - gotAccept._isAvaliable = true; - } + + + + + + + + + + + + + + + + + + + /* +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //const auto testval = bufferBitSizeMax; + if ((bufBitPos >= (8 * msgBytes) - syncBits) && !isMsgAvaliable) { + switch ((rawBuffer[0] >> 5) & IR_MASK_MSG_TYPE) { + case IR_MSG_ACCEPT: + if (bufBitPos >= ((msgBytes + addrBytes + crcBytes) * (8 + 3)) - syncBits) { + const uint8_t dataSize = msgBytes + addrBytes; + isRawAvaliable = true; + isMsgAvaliable = crcCheck(dataSize); + if (isMsgAvaliable && checkAddr(1, 2)) { + gotAccept._set(dataBuffer, msgBytes + addrBytes + crcBytes, crcValue, errorCounter, riseSyncTime); + gotAccept._isAvaliable = true; } - break; + } + break; - case IR_MSG_REQUEST: - if (bufBitPos >= ((msgBytes + addrBytes + addrBytes + crcBytes) * (8 + 3)) - syncBits) { - const uint8_t dataSize = msgBytes + addrBytes + addrBytes; - isRawAvaliable = true; - isMsgAvaliable = (crcCheck(dataSize)); - if (isMsgAvaliable && checkAddr(3, 4)) { - gotRequest._isAvaliable = true; - gotRequest._set(dataBuffer, msgBytes + addrBytes + addrBytes + crcBytes, crcValue, errorCounter, riseSyncTime); - } + case IR_MSG_REQUEST: + if (bufBitPos >= ((msgBytes + addrBytes + addrBytes + crcBytes) * (8 + 3)) - syncBits) { + const uint8_t dataSize = msgBytes + addrBytes + addrBytes; + isRawAvaliable = true; + isMsgAvaliable = (crcCheck(dataSize)); + if (isMsgAvaliable && checkAddr(3, 4)) { + gotRequest._isAvaliable = true; + gotRequest._set(dataBuffer, msgBytes + addrBytes + addrBytes + crcBytes, crcValue, errorCounter, riseSyncTime); } - break; + } + break; - case IR_MSG_DATA_ACCEPT: - case IR_MSG_DATA_NOACCEPT: - if (bufBitPos >= ((bitPerByte + syncBits) * ((rawBuffer[0] & IR_MASK_MSG_INFO) + crcBytes)) - syncBits) { - const uint8_t dataSize = (rawBuffer[0] & IR_MASK_MSG_INFO); - isRawAvaliable = true; - isMsgAvaliable = crcCheck(dataSize); - if (isMsgAvaliable && checkAddr(3, 4)) { - gotData._isAvaliable = true; - gotData._set(dataBuffer, (dataSize)+crcBytes, crcValue, errorCounter, riseSyncTime); - } else { - gotRawData._isAvaliable = true; - gotRawData._set(dataBuffer, (dataSize)+crcBytes, crcValue, errorCounter, riseSyncTime); - } + case IR_MSG_DATA_ACCEPT: + case IR_MSG_DATA_NOACCEPT: + if (bufBitPos >= ((bitPerByte + syncBits) * ((rawBuffer[0] & IR_MASK_MSG_INFO) + crcBytes)) - syncBits) { + const uint8_t dataSize = (rawBuffer[0] & IR_MASK_MSG_INFO); + isRawAvaliable = true; + isMsgAvaliable = crcCheck(dataSize); + if (isMsgAvaliable && checkAddr(3, 4)) { + gotData._isAvaliable = true; + gotData._set(dataBuffer, (dataSize)+crcBytes, crcValue, errorCounter, riseSyncTime); + } else { + gotRawData._isAvaliable = true; + gotRawData._set(dataBuffer, (dataSize)+crcBytes, crcValue, errorCounter, riseSyncTime); } - break; + } + break; - default: - break; - } - }/**/ - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -} - -uint8_t* IR_Decoder::getDataBuffer(bool reset = false) { - if (!isRawAvaliable) { return nullptr; } - if (dataBuffer != nullptr) { delete dataBuffer; dataBuffer = nullptr; } // устранение утечки памяти - dataBuffer = new uint8_t[dataByteSizeMax] { 0 }; // Буффер по максимуму - - bool isData = true; - bool controlCheckFirst = true; - bool controlCheck; - - uint8_t nextControlBit = bitPerByte; - uint16_t i_dataBuffer = 0; - for (uint16_t i = 0; i < dataBitSize; i++) { - if (i == nextControlBit) { - controlCheckFirst = true; - nextControlBit += (isData ? syncBits : bitPerByte); - isData = !isData; - } - - if (isData) { - dataBuffer[i_dataBuffer / 8] |= (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1) << 7 - (i_dataBuffer % 8); - i_dataBuffer++; - } else { // Проверка контрольных sync битов - if (controlCheckFirst) { - controlCheck = (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1); - controlCheckFirst = false; - } else { - controlCheck |= (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1); + default: + break; } + }/**/ + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - } - } - - isFilterBufferAvaliable = controlCheck; - if (reset) { resetAvaliable(); } - return dataBuffer; } +// uint8_t* IR_Decoder::getDataBuffer(bool reset = false) { +// if (!isRawAvaliable) { return nullptr; } +// if (dataBuffer != nullptr) { delete dataBuffer; dataBuffer = nullptr; } // устранение утечки памяти +// dataBuffer = new uint8_t[dataByteSizeMax] { 0 }; // Буффер по максимуму + +// bool isData = true; +// bool controlCheckFirst = true; +// bool controlCheck; + +// uint8_t nextControlBit = bitPerByte; +// uint16_t i_dataBuffer = 0; +// for (uint16_t i = 0; i < dataBitSize; i++) { +// if (i == nextControlBit) { +// controlCheckFirst = true; +// nextControlBit += (isData ? syncBits : bitPerByte); +// isData = !isData; +// } + +// if (isData) { +// dataBuffer[i_dataBuffer / 8] |= (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1) << 7 - (i_dataBuffer % 8); +// i_dataBuffer++; +// } else { // Проверка контрольных sync битов +// if (controlCheckFirst) { +// controlCheck = (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1); +// controlCheckFirst = false; +// } else { +// controlCheck |= (rawBuffer[(i / 8)] >> (7 - (i % 8)) & 1); +// } + +// } +// } + +// isFilterBufferAvaliable = controlCheck; +// if (reset) { resetAvaliable(); } +// return dataBuffer; +// } + bool IR_Decoder::crcCheck(uint8_t len) { bool crcOK = false; // получить буффер, если нет @@ -208,13 +217,14 @@ void IR_Decoder::start_RX() { resetAvaliable(); isBufferOverflow = false; - memset(rawBuffer, 0x00, bufferRawSize); + memset(dataBuffer, 0x00, bufferDataSize); bufBitPos = 0; isData = true; i_dataBuffer = 0; nextControlBit = bitPerByte; i_syncBit = 0; + isWrongPack = false; } void IR_Decoder::resetAvaliable() { @@ -250,13 +260,19 @@ void IR_Decoder::tick() { interrupts(); //////////////////////////////////////////////////////////////////////////////////////////////////////////// - if (currentFront.time - prevRise > IR_timeout && currentFront.dir) { // первый ↑ + if (currentFront.time - prevRise > IR_timeout) { // первый + // if (!currentFront.dir) { // ↓ + + errorCounter = 0; isRecive = true; isPreamb = true; - frontCounter = preambFronts - 1U; - errorCounter = 0; + // frontCounter = preambFronts - 1U; + // } else { // ↑ riseSyncTime = bitTime /* 1100 */; start_RX(); + frontCounter = preambFronts - 1U; + + // } // Serial.println(); // Serial.print("currentFront.time: "); Serial.println(currentFront.time); @@ -286,7 +302,6 @@ void IR_Decoder::tick() { } isPreamb = false; } - // определить направление фронта if (currentFront.dir) { // Если __/``` ↑ @@ -297,8 +312,10 @@ void IR_Decoder::tick() { int8_t highCount = 0; int8_t lowCount = 0; int8_t allCount = 0; + bool invertErr = false; - if (risePeriod < IR_timeout && !isBufferOverflow && risePeriod > riseTimeMin) { + + if (risePeriod < IR_timeout && !isBufferOverflow && risePeriod > riseTimeMin && !isWrongPack) { // Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц if (aroundRise(risePeriod)) { // тактирование есть, сигнал хороший - без ошибок(?) @@ -339,7 +356,13 @@ void IR_Decoder::tick() { #ifdef IRDEBUG errPulse(errOut, 4); #endif - } else if (lowCount == highCount) {} // неизвестный случай + // неизвестный случай Инверсит след бит или соседние + // Очень редко + // TODO: Отловить проверить + } else if (lowCount == highCount) { + invertErr = true; + Serial.print("..."); + } errorCounter += allCount; } @@ -349,17 +372,33 @@ void IR_Decoder::tick() { #endif for (int8_t i = 0; i < lowCount && 8 - i; i++) { // отправка LOW битов, если есть - writeToBuffer(LOW); - #ifdef IRDEBUG - digitalWrite(wrLow, 1); - #endif + if (i == lowCount - 1 && invertErr) { + invertErr = false; + writeToBuffer(!LOW); + #ifdef IRDEBUG + digitalWrite(wrLow, 1); + #endif + } else { + writeToBuffer(LOW); + #ifdef IRDEBUG + digitalWrite(wrLow, 1); + #endif + } } for (int8_t i = 0; i < highCount && 8 - i; i++) { // отправка HIGH битов, если есть - writeToBuffer(HIGH); - #ifdef IRDEBUG - digitalWrite(wrHigh, 1); - #endif + if (i == highCount - 1 && invertErr) { + invertErr = false; + writeToBuffer(!HIGH); + #ifdef IRDEBUG + digitalWrite(wrLow, 1); + #endif + } else { + writeToBuffer(HIGH); + #ifdef IRDEBUG + digitalWrite(wrHigh, 1); + #endif + } } } #ifdef IRDEBUG @@ -427,7 +466,7 @@ void IR_Decoder::isr() { // в прерывании вызываем isr() } - currentSubBufferIndex == (subBufferSize - 1) ? currentSubBufferIndex = 0 : currentSubBufferIndex++; + currentSubBufferIndex == (subBufferSize - 1) ? currentSubBufferIndex = 0 : currentSubBufferIndex++; // Закольцовка буффера } diff --git a/IR_Decoder.h b/IR_Decoder.h index d93b8dc..95b05f8 100644 --- a/IR_Decoder.h +++ b/IR_Decoder.h @@ -19,7 +19,7 @@ #define riseTimeMax (riseTime + riseTolerance) #define riseTimeMin (riseTime - riseTolerance) #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 //Буфер для складирования фронтов, пока их не обработают @@ -188,15 +188,16 @@ private: volatile bool isFilterBufferAvaliable = false; volatile bool isBufferOverflow = false; + bool isWrongPack = false; volatile bool isPreamb = false; // флаг начальной последовости bool HIGH_FIRST = true; // порядок приходящих битов //Буффер - const uint8_t bufferRawSize = - ((bufferBitSizeMax % 8 > 0) ? - (bufferBitSizeMax / 8) + 1 : - (bufferBitSizeMax / 8)); + // const uint8_t bufferRawSize = + // ((bufferBitSizeMax % 8 > 0) ? + // (bufferBitSizeMax / 8) + 1 : + // (bufferBitSizeMax / 8)); const uint8_t bufferDataSize = dataByteSizeMax; // + crc //////////////////////////////////////////////////////////////////////// void noFunc(); @@ -220,7 +221,7 @@ private: volatile FrontStorage* firstUnHandledFront = nullptr; // Указатель первого необработанного фронта/спада volatile FrontStorage subBuffer[subBufferSize]; // вспомогательный буфер для хранения необработанных фронтов/спадов //////////////////////////////////////////////////////////////////////// - uint8_t* rawBuffer = nullptr; + // uint8_t* rawBuffer = nullptr; uint8_t* dataBuffer = nullptr; volatile uint32_t prevRise, prevFall, prevPrevFall, prevPrevRise; @@ -236,6 +237,7 @@ private: uint16_t i_dataBuffer; // Счётчик буфера данных uint8_t nextControlBit = bitPerByte; // Метка для смены флага isData uint8_t i_syncBit; // Счётчик битов синхронизации + uint8_t err_syncBit; // Счётчик ошибок синхронизации void writeToBuffer(bool); //////////////////////////////////////////////////////////////////////// void start_RX();