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,174 +7,183 @@
) )
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("****************");
}//**************************************************************************************************//
// if (bufBitPos >= bufferRawSize * 8 - 1) { isBufferOverflow = true; } // Serial.print(bit);
/*
#ifdef IRDEBUG #ifdef IRDEBUG
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1); bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
#endif #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: case IR_MSG_REQUEST:
if (bufBitPos >= ((msgBytes + addrBytes + addrBytes + crcBytes) * (8 + 3)) - syncBits) { if (bufBitPos >= ((msgBytes + addrBytes + addrBytes + crcBytes) * (8 + 3)) - syncBits) {
const uint8_t dataSize = msgBytes + addrBytes + addrBytes; const uint8_t dataSize = msgBytes + addrBytes + addrBytes;
isRawAvaliable = true; isRawAvaliable = true;
isMsgAvaliable = (crcCheck(dataSize)); isMsgAvaliable = (crcCheck(dataSize));
if (isMsgAvaliable && checkAddr(3, 4)) { if (isMsgAvaliable && checkAddr(3, 4)) {
gotRequest._isAvaliable = true; gotRequest._isAvaliable = true;
gotRequest._set(dataBuffer, msgBytes + addrBytes + addrBytes + crcBytes, crcValue, errorCounter, riseSyncTime); gotRequest._set(dataBuffer, msgBytes + addrBytes + addrBytes + crcBytes, crcValue, errorCounter, riseSyncTime);
}
} }
break; }
break;
case IR_MSG_DATA_ACCEPT: case IR_MSG_DATA_ACCEPT:
case IR_MSG_DATA_NOACCEPT: case IR_MSG_DATA_NOACCEPT:
if (bufBitPos >= ((bitPerByte + syncBits) * ((rawBuffer[0] & IR_MASK_MSG_INFO) + crcBytes)) - syncBits) { if (bufBitPos >= ((bitPerByte + syncBits) * ((rawBuffer[0] & IR_MASK_MSG_INFO) + crcBytes)) - syncBits) {
const uint8_t dataSize = (rawBuffer[0] & IR_MASK_MSG_INFO); const uint8_t dataSize = (rawBuffer[0] & IR_MASK_MSG_INFO);
isRawAvaliable = true; isRawAvaliable = true;
isMsgAvaliable = crcCheck(dataSize); isMsgAvaliable = crcCheck(dataSize);
if (isMsgAvaliable && checkAddr(3, 4)) { if (isMsgAvaliable && checkAddr(3, 4)) {
gotData._isAvaliable = true; gotData._isAvaliable = true;
gotData._set(dataBuffer, (dataSize)+crcBytes, crcValue, errorCounter, riseSyncTime); gotData._set(dataBuffer, (dataSize)+crcBytes, crcValue, errorCounter, riseSyncTime);
} else { } else {
gotRawData._isAvaliable = true; gotRawData._isAvaliable = true;
gotRawData._set(dataBuffer, (dataSize)+crcBytes, crcValue, errorCounter, riseSyncTime); gotRawData._set(dataBuffer, (dataSize)+crcBytes, crcValue, errorCounter, riseSyncTime);
}
} }
break; }
break;
default: default:
break; 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);
} }
}/**/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
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 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,17 +372,33 @@ 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 битов, если есть
writeToBuffer(LOW); if (i == lowCount - 1 && invertErr) {
#ifdef IRDEBUG invertErr = false;
digitalWrite(wrLow, 1); writeToBuffer(!LOW);
#endif #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 битов, если есть for (int8_t i = 0; i < highCount && 8 - i; i++) { // отправка HIGH битов, если есть
writeToBuffer(HIGH); if (i == highCount - 1 && invertErr) {
#ifdef IRDEBUG invertErr = false;
digitalWrite(wrHigh, 1); writeToBuffer(!HIGH);
#endif #ifdef IRDEBUG
digitalWrite(wrLow, 1);
#endif
} else {
writeToBuffer(HIGH);
#ifdef IRDEBUG
digitalWrite(wrHigh, 1);
#endif
}
} }
} }
#ifdef IRDEBUG #ifdef IRDEBUG
@ -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();