mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2025-05-04 15:20:16 +00:00
fix extra zero, docs and debag
This commit is contained in:
parent
56c207b058
commit
d629b24864
203
IR_Decoder.cpp
203
IR_Decoder.cpp
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
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;
|
||||||
prevRise = prevFall = prevPrevFall = prevPrevRise = 0;
|
prevRise = prevFall = prevPrevFall = prevPrevRise = 0;
|
||||||
start_RX();
|
start_RX();
|
||||||
}
|
}
|
||||||
@ -17,73 +18,117 @@ IR_Decoder::~IR_Decoder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IR_Decoder::writeToBuffer(bool bit) {
|
void IR_Decoder::writeToBuffer(bool bit) {
|
||||||
if (!isBufferOverflow && !isPreamb) {
|
if (isBufferOverflow || isPreamb) return;
|
||||||
if (HIGH_FIRST) {
|
|
||||||
rawBuffer[(bufBitPos >> 3)] |= bit << (7 - (bufBitPos & ~(~0 << 3)));
|
|
||||||
}/* else {
|
|
||||||
rawBuffer[(bufBitPos >> 3)] |= bit << (bufBitPos & ~(~0 << 3));
|
|
||||||
} */
|
|
||||||
Serial.print(bit);
|
|
||||||
#ifdef IRDEBUG
|
|
||||||
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (isBufferOverflow) { //TODO: Буффер переполнен!
|
// Переключение флага, data или syncBit
|
||||||
|
if (bufBitPos == nextControlBit) {
|
||||||
}
|
nextControlBit += (isData ? syncBits : bitPerByte);
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
isData = !isData;
|
||||||
//const auto testval = bufferBitSizeMax;
|
Serial.print(" ");
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
if (bufBitPos >= bufferRawSize * 8 - 1) { isBufferOverflow = true; }
|
|
||||||
bufBitPos++;
|
|
||||||
}
|
}
|
||||||
|
Serial.print(bit);
|
||||||
|
|
||||||
|
if (isData) { // Запись битов в dataBuffer
|
||||||
|
dataBuffer[(i_dataBuffer / 8)] |= bit << (7 - i_dataBuffer%8);
|
||||||
|
i_dataBuffer++;
|
||||||
|
bufBitPos++;
|
||||||
|
i_syncBit = 0;
|
||||||
|
} else { // Проверка контрольных sync битов
|
||||||
|
if (i_syncBit == 0) { // Первый бит синхронизации
|
||||||
|
if (bit != dataBuffer[((i_dataBuffer - 1) / 8)] & 1 << (7 - ((i_dataBuffer - 1) & ~(~0 << 3)))) {
|
||||||
|
bufBitPos++;
|
||||||
|
} else {
|
||||||
|
errorCounter++;
|
||||||
|
Serial.print("E");
|
||||||
|
// Serial.print("bit: ");Serial.println(bit);
|
||||||
|
// Serial.print("dataBuffer: ");Serial.println(dataBuffer[((i_dataBuffer - 1) / 8)] & 1 << (7 - ((i_dataBuffer - 1) & ~(~0 << 3))));
|
||||||
|
}
|
||||||
|
} else { // Последующие биты синхронизации
|
||||||
|
bufBitPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i_syncBit++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (bufBitPos >= bufferRawSize * 8 - 1) { isBufferOverflow = true; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}/**/
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* IR_Decoder::getDataBuffer(bool reset = false) {
|
uint8_t* IR_Decoder::getDataBuffer(bool reset = false) {
|
||||||
@ -149,10 +194,20 @@ bool IR_Decoder::crcCheck(uint8_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IR_Decoder::start_RX() {
|
void IR_Decoder::start_RX() {
|
||||||
|
// Serial.println();
|
||||||
|
// Serial.println(printBytes(dataBuffer, dataByteSizeMax-1, BIN));
|
||||||
|
// Serial.println();
|
||||||
|
|
||||||
|
|
||||||
resetAvaliable();
|
resetAvaliable();
|
||||||
isBufferOverflow = false;
|
isBufferOverflow = false;
|
||||||
memset(rawBuffer, 0x00, bufferRawSize);
|
memset(rawBuffer, 0x00, bufferRawSize);
|
||||||
|
|
||||||
bufBitPos = 0;
|
bufBitPos = 0;
|
||||||
|
isData = true;
|
||||||
|
i_dataBuffer = 0;
|
||||||
|
nextControlBit = bitPerByte;
|
||||||
|
i_syncBit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IR_Decoder::resetAvaliable() {
|
void IR_Decoder::resetAvaliable() {
|
||||||
@ -308,14 +363,14 @@ void IR_Decoder::tick() {
|
|||||||
void IR_Decoder::isr() { // в прерывании вызываем isr()
|
void IR_Decoder::isr() { // в прерывании вызываем isr()
|
||||||
if (isPairSending) return;
|
if (isPairSending) return;
|
||||||
|
|
||||||
frontBuffer[currentFrontBufferWriteIndex].next = nullptr;
|
subBuffer[currentSubBufferIndex].next = nullptr;
|
||||||
frontBuffer[currentFrontBufferWriteIndex].dir = (PIND >> isrPin) & 1;
|
subBuffer[currentSubBufferIndex].dir = (PIND >> isrPin) & 1;
|
||||||
frontBuffer[currentFrontBufferWriteIndex].time = micros();
|
subBuffer[currentSubBufferIndex].time = micros();
|
||||||
|
|
||||||
if (firstUnHandledFront == nullptr) {
|
if (firstUnHandledFront == nullptr) {
|
||||||
firstUnHandledFront = &frontBuffer[currentFrontBufferWriteIndex]; // Если нет необработанных данных - добавляем их
|
firstUnHandledFront = &subBuffer[currentSubBufferIndex]; // Если нет необработанных данных - добавляем их
|
||||||
} else {
|
} else {
|
||||||
if (firstUnHandledFront == &frontBuffer[currentFrontBufferWriteIndex]) { // Если контроллер не успел обработать новый сигнал, принудительно пропускаем его
|
if (firstUnHandledFront == &subBuffer[currentSubBufferIndex]) { // Если контроллер не успел обработать новый сигнал, принудительно пропускаем его
|
||||||
firstUnHandledFront = firstUnHandledFront->next;
|
firstUnHandledFront = firstUnHandledFront->next;
|
||||||
Serial.println();
|
Serial.println();
|
||||||
Serial.println("ERROR");
|
Serial.println("ERROR");
|
||||||
@ -324,14 +379,14 @@ void IR_Decoder::isr() { // в прерывании вызываем isr()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lastFront == nullptr) {
|
if (lastFront == nullptr) {
|
||||||
lastFront = &frontBuffer[currentFrontBufferWriteIndex];
|
lastFront = &subBuffer[currentSubBufferIndex];
|
||||||
} else {
|
} else {
|
||||||
lastFront->next = &frontBuffer[currentFrontBufferWriteIndex];
|
lastFront->next = &subBuffer[currentSubBufferIndex];
|
||||||
lastFront = &frontBuffer[currentFrontBufferWriteIndex];
|
lastFront = &subBuffer[currentSubBufferIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
currentFrontBufferWriteIndex == (subBuffer - 1) ? currentFrontBufferWriteIndex = 0 : currentFrontBufferWriteIndex++;
|
currentSubBufferIndex == (subBufferSize - 1) ? currentSubBufferIndex = 0 : currentSubBufferIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
29
IR_Decoder.h
29
IR_Decoder.h
@ -21,7 +21,7 @@
|
|||||||
#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 subBuffer 5 //Буфер для складирования фронтов, пока их не обработают
|
#define subBufferSize 15 //Буфер для складирования фронтов, пока их не обработают
|
||||||
|
|
||||||
class IR_Encoder;
|
class IR_Encoder;
|
||||||
class IR_Decoder : private IR_FOX {
|
class IR_Decoder : private IR_FOX {
|
||||||
@ -200,12 +200,14 @@ private:
|
|||||||
const uint8_t bufferDataSize = dataByteSizeMax; // + crc
|
const uint8_t bufferDataSize = dataByteSizeMax; // + crc
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
void noFunc();
|
void noFunc();
|
||||||
volatile uint8_t currentFrontBufferWriteIndex;
|
volatile uint8_t currentSubBufferIndex; // Счетчик текущей позиции во вспомогательном буфере фронтов/спадов
|
||||||
|
// Структура для хранения времени и направления фронта/спада
|
||||||
struct FrontStorage {
|
struct FrontStorage {
|
||||||
volatile uint32_t time;
|
volatile uint32_t time; // Время
|
||||||
volatile bool dir;
|
volatile bool dir; // Направление (true = ↑; false = ↓)
|
||||||
volatile FrontStorage* next;
|
volatile FrontStorage* next; // Указатель на следующий связанный фронт/спад, или nullptr если конец
|
||||||
|
|
||||||
|
// Операторо присвоения
|
||||||
FrontStorage& operator= (FrontStorage& val) {
|
FrontStorage& operator= (FrontStorage& val) {
|
||||||
this->next = val.next;
|
this->next = val.next;
|
||||||
this->time = val.time;
|
this->time = val.time;
|
||||||
@ -214,9 +216,9 @@ private:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
volatile FrontStorage* lastFront = nullptr;
|
volatile FrontStorage* lastFront = nullptr; // Указатель последнего фронта/спада
|
||||||
volatile FrontStorage* firstUnHandledFront = nullptr;
|
volatile FrontStorage* firstUnHandledFront = nullptr; // Указатель первого необработанного фронта/спада
|
||||||
volatile FrontStorage frontBuffer[subBuffer];
|
volatile FrontStorage subBuffer[subBufferSize]; // вспомогательный буфер для хранения необработанных фронтов/спадов
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
uint8_t* rawBuffer = nullptr;
|
uint8_t* rawBuffer = nullptr;
|
||||||
uint8_t* dataBuffer = nullptr;
|
uint8_t* dataBuffer = nullptr;
|
||||||
@ -229,9 +231,14 @@ private:
|
|||||||
private:
|
private:
|
||||||
uint8_t* getDataBuffer(bool reset = false);
|
uint8_t* getDataBuffer(bool reset = false);
|
||||||
bool crcCheck(uint8_t len);
|
bool crcCheck(uint8_t len);
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
inline void writeToBuffer(bool);
|
bool isData = true; // Флаг относится ли бит к данным, или битам синхронизации
|
||||||
inline void start_RX();
|
uint16_t i_dataBuffer; // Счётчик буфера данных
|
||||||
|
uint8_t nextControlBit = bitPerByte; // Метка для смены флага isData
|
||||||
|
uint8_t i_syncBit; // Счётчик битов синхронизации
|
||||||
|
void writeToBuffer(bool);
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
void start_RX();
|
||||||
void resetAvaliable();
|
void resetAvaliable();
|
||||||
|
|
||||||
uint16_t ceil_div(uint16_t, uint16_t);
|
uint16_t ceil_div(uint16_t, uint16_t);
|
||||||
|
@ -146,7 +146,7 @@ public:
|
|||||||
case 2:
|
case 2:
|
||||||
for (size_t i = 0; i < s * 8; i++) {
|
for (size_t i = 0; i < s * 8; i++) {
|
||||||
if (i == control) {
|
if (i == control) {
|
||||||
str += " ";
|
str += " ";
|
||||||
control += bitPerByte;
|
control += bitPerByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user