mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2025-05-04 15:20:16 +00:00
check sync bits, fix rare invert error
This commit is contained in:
parent
b05b9dc9d5
commit
6691915aa0
163
IR_Decoder.cpp
163
IR_Decoder.cpp
@ -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++; // Закольцовка буффера
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
14
IR_Decoder.h
14
IR_Decoder.h
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user