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) {
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("****************");
}//**************************************************************************************************//
// Serial.print(bit);
#ifdef IRDEBUG
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
#endif
// if (bufBitPos >= bufferRawSize * 8 - 1) { isBufferOverflow = true; }
@ -78,13 +94,6 @@ void IR_Decoder::writeToBuffer(bool bit) {
/*
#ifdef IRDEBUG
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
#endif
if (isBufferOverflow) { //TODO: Буффер переполнен!
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//const auto testval = bufferBitSizeMax;
if ((bufBitPos >= (8 * msgBytes) - syncBits) && !isMsgAvaliable) {
@ -138,42 +147,42 @@ void IR_Decoder::writeToBuffer(bool bit) {
}
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 }; // Буффер по максимуму
// 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;
// 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;
}
// 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);
}
// 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;
}
// 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,19 +372,35 @@ void IR_Decoder::tick() {
#endif
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);
#ifdef IRDEBUG
digitalWrite(wrLow, 1);
#endif
}
}
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);
#ifdef IRDEBUG
digitalWrite(wrHigh, 1);
#endif
}
}
}
#ifdef IRDEBUG
digitalWrite(wrHigh, 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 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();