mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2025-05-04 07:10:16 +00:00
isr optimizations
This commit is contained in:
parent
d8283620b7
commit
56c207b058
177
IR_Decoder.cpp
177
IR_Decoder.cpp
@ -23,7 +23,7 @@ void IR_Decoder::writeToBuffer(bool bit) {
|
|||||||
}/* else {
|
}/* else {
|
||||||
rawBuffer[(bufBitPos >> 3)] |= bit << (bufBitPos & ~(~0 << 3));
|
rawBuffer[(bufBitPos >> 3)] |= bit << (bufBitPos & ~(~0 << 3));
|
||||||
} */
|
} */
|
||||||
|
Serial.print(bit);
|
||||||
#ifdef IRDEBUG
|
#ifdef IRDEBUG
|
||||||
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
|
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
|
||||||
#endif
|
#endif
|
||||||
@ -31,7 +31,7 @@ void IR_Decoder::writeToBuffer(bool bit) {
|
|||||||
if (isBufferOverflow) { //TODO: Буффер переполнен!
|
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) {
|
||||||
@ -80,7 +80,7 @@ void IR_Decoder::writeToBuffer(bool bit) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
if (bufBitPos >= bufferRawSize * 8 - 1) { isBufferOverflow = true; }
|
if (bufBitPos >= bufferRawSize * 8 - 1) { isBufferOverflow = true; }
|
||||||
bufBitPos++;
|
bufBitPos++;
|
||||||
}
|
}
|
||||||
@ -168,19 +168,27 @@ uint16_t IR_Decoder::ceil_div(uint16_t val, uint16_t divider) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IR_Decoder::listen(){
|
void IR_Decoder::listen() {
|
||||||
if(isRecive && micros()-prevRise > IR_timeout*2) {isRecive = false;}
|
if (isRecive && micros() - prevRise > IR_timeout * 2) {
|
||||||
|
isRecive = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////// isr ///////////////////////////////////////////
|
//////////////////////////////////// isr ///////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void IR_Decoder::tick() {
|
||||||
|
if (firstUnHandledFront == nullptr) return; //Если данных нет - ничего не делаем
|
||||||
|
|
||||||
void IR_Decoder::isr() { // в прерывании вызываем isr()
|
FrontStorage currentFront;
|
||||||
if (isPairSending) return;
|
//найти следующий необработанный фронт/спад
|
||||||
|
noInterrupts();
|
||||||
|
currentFront = *((FrontStorage*)firstUnHandledFront);
|
||||||
|
interrupts();
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if (micros() - prevRise > IR_timeout) { // первый
|
if (currentFront.time - prevRise > IR_timeout && currentFront.dir) { // первый ↑
|
||||||
isRecive = true;
|
isRecive = true;
|
||||||
isPreamb = true;
|
isPreamb = true;
|
||||||
frontCounter = preambFronts - 1U;
|
frontCounter = preambFronts - 1U;
|
||||||
@ -188,6 +196,156 @@ void IR_Decoder::isr() { // в прерывании вызываем isr()
|
|||||||
riseSyncTime = bitTime /* 1100 */;
|
riseSyncTime = bitTime /* 1100 */;
|
||||||
start_RX();
|
start_RX();
|
||||||
|
|
||||||
|
// Serial.println();
|
||||||
|
// Serial.print("currentFront.time: "); Serial.println(currentFront.time);
|
||||||
|
// Serial.print("currentFront.dir: "); Serial.println(currentFront.dir ? "UP" : "Down");
|
||||||
|
// Serial.print("prevRise: "); Serial.println(prevRise);
|
||||||
|
// Serial.print("frontCounter: "); Serial.println(frontCounter);
|
||||||
|
|
||||||
|
// prevRise = currentFront.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontCounter > 0) { // в преамбуле
|
||||||
|
uint32_t risePeriod = currentFront.time - prevRise;
|
||||||
|
if (currentFront.dir && risePeriod < IR_timeout) { // __/``` ↑ и мы в внутри пакета
|
||||||
|
|
||||||
|
if (risePeriod < riseTimeMin << 1) { // fix рваной единицы
|
||||||
|
frontCounter += 2;
|
||||||
|
errorCounter++;
|
||||||
|
} else {
|
||||||
|
if (freeFrec) { riseSyncTime = (riseSyncTime + risePeriod / 2) / 2; } // tuner
|
||||||
|
}
|
||||||
|
} else { /* riseSyncTime = bitTime; */ } // сброс тюнера
|
||||||
|
frontCounter--;
|
||||||
|
// Serial.print("frontCounter: "); Serial.println(frontCounter);
|
||||||
|
} else {
|
||||||
|
if (isPreamb) {// первый фронт после
|
||||||
|
gotTune._set(riseSyncTime);
|
||||||
|
}
|
||||||
|
isPreamb = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// определить направление фронта
|
||||||
|
if (currentFront.dir) { // Если __/``` ↑
|
||||||
|
|
||||||
|
uint16_t risePeriod = currentFront.time - prevRise;
|
||||||
|
uint16_t highTime = currentFront.time - prevFall;
|
||||||
|
uint16_t lowTime = prevFall - prevRise;
|
||||||
|
|
||||||
|
int8_t highCount = 0;
|
||||||
|
int8_t lowCount = 0;
|
||||||
|
int8_t allCount = 0;
|
||||||
|
|
||||||
|
if (risePeriod < IR_timeout && !isBufferOverflow && risePeriod > riseTimeMin) {
|
||||||
|
// Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц
|
||||||
|
|
||||||
|
if (aroundRise(risePeriod)) { // тактирование есть, сигнал хороший - без ошибок(?)
|
||||||
|
|
||||||
|
if (highTime > riseTimeMin >> 1) { // 1
|
||||||
|
writeToBuffer(HIGH);
|
||||||
|
} else { // 0
|
||||||
|
writeToBuffer(LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // пропущены такты! сигнал средний // ошибка пропуска
|
||||||
|
highCount = ceil_div(highTime, riseTime); // предполагаемое колличество HIGH битов
|
||||||
|
lowCount = ceil_div(lowTime, riseTime); // предполагаемое колличество LOW битов
|
||||||
|
allCount = ceil_div(risePeriod, riseTime); // предполагаемое колличество всего битов
|
||||||
|
|
||||||
|
if (highCount == 0 && highTime > riseTime / 3) { // fix короткой единицы (?)после пропуска нулей(?)
|
||||||
|
highCount++;
|
||||||
|
errorCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lowCount + highCount > allCount) { // fix ошибочных сдвигов
|
||||||
|
if (lowCount > highCount) { // Лишние нули
|
||||||
|
lowCount = allCount - highCount;
|
||||||
|
} else if (lowCount < highCount) { // Лишние единицы
|
||||||
|
highCount = allCount - lowCount;
|
||||||
|
} else if (lowCount == highCount) {} // неизвестный случай
|
||||||
|
errorCounter += allCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCounter += allCount;
|
||||||
|
|
||||||
|
for (int8_t i = 0; i < lowCount && 8 - i; i++) { // отправка LOW битов, если есть
|
||||||
|
writeToBuffer(LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int8_t i = 0; i < highCount && 8 - i; i++) { // отправка HIGH битов, если есть
|
||||||
|
writeToBuffer(HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (risePeriod > riseTimeMax / 2 || highCount || lowCount) { // комплексный фикс рваной единицы
|
||||||
|
prevPrevRise = prevRise;
|
||||||
|
prevRise = currentFront.time;
|
||||||
|
} else {
|
||||||
|
errorCounter++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // Если ```\__ ↓
|
||||||
|
|
||||||
|
if (currentFront.time - prevFall > riseTimeMin) {
|
||||||
|
prevPrevFall = prevFall;
|
||||||
|
prevFall = currentFront.time;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPreamb && frontCounter <= 0) {
|
||||||
|
prevRise = currentFront.time + riseTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
firstUnHandledFront = firstUnHandledFront->next; //переместить флаг на следующий элемент (next or nullptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
void IR_Decoder::isr() { // в прерывании вызываем isr()
|
||||||
|
if (isPairSending) return;
|
||||||
|
|
||||||
|
frontBuffer[currentFrontBufferWriteIndex].next = nullptr;
|
||||||
|
frontBuffer[currentFrontBufferWriteIndex].dir = (PIND >> isrPin) & 1;
|
||||||
|
frontBuffer[currentFrontBufferWriteIndex].time = micros();
|
||||||
|
|
||||||
|
if (firstUnHandledFront == nullptr) {
|
||||||
|
firstUnHandledFront = &frontBuffer[currentFrontBufferWriteIndex]; // Если нет необработанных данных - добавляем их
|
||||||
|
} else {
|
||||||
|
if (firstUnHandledFront == &frontBuffer[currentFrontBufferWriteIndex]) { // Если контроллер не успел обработать новый сигнал, принудительно пропускаем его
|
||||||
|
firstUnHandledFront = firstUnHandledFront->next;
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("ERROR");
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastFront == nullptr) {
|
||||||
|
lastFront = &frontBuffer[currentFrontBufferWriteIndex];
|
||||||
|
} else {
|
||||||
|
lastFront->next = &frontBuffer[currentFrontBufferWriteIndex];
|
||||||
|
lastFront = &frontBuffer[currentFrontBufferWriteIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
currentFrontBufferWriteIndex == (subBuffer - 1) ? currentFrontBufferWriteIndex = 0 : currentFrontBufferWriteIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IR_Decoder::noFunc() {
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if (micros() - prevRise > IR_timeout && (PIND >> isrPin) & 1) { // первый
|
||||||
|
isRecive = true;
|
||||||
|
isPreamb = true;
|
||||||
|
frontCounter = preambFronts - 1U;
|
||||||
|
errorCounter = 0;
|
||||||
|
riseSyncTime = bitTime /* 1100 */;
|
||||||
|
start_RX();
|
||||||
|
Serial.println("First!");
|
||||||
|
|
||||||
}
|
}
|
||||||
if (frontCounter > 0) { // в преамбуле
|
if (frontCounter > 0) { // в преамбуле
|
||||||
uint32_t risePeriod = micros() - prevRise;
|
uint32_t risePeriod = micros() - prevRise;
|
||||||
@ -206,7 +364,7 @@ void IR_Decoder::isr() { // в прерывании вызываем isr()
|
|||||||
if (isPreamb) {// первый фронт после
|
if (isPreamb) {// первый фронт после
|
||||||
gotTune._set(riseSyncTime);
|
gotTune._set(riseSyncTime);
|
||||||
}
|
}
|
||||||
isPreamb = false;
|
isPreamb = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// определить направление фронта
|
// определить направление фронта
|
||||||
@ -325,6 +483,7 @@ void IR_Decoder::isr() { // в прерывании вызываем isr()
|
|||||||
#ifdef IRDEBUG
|
#ifdef IRDEBUG
|
||||||
digitalWrite(writeOp, isPreamb);
|
digitalWrite(writeOp, isPreamb);
|
||||||
#endif
|
#endif
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
26
IR_Decoder.h
26
IR_Decoder.h
@ -21,6 +21,8 @@
|
|||||||
#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 //Буфер для складирования фронтов, пока их не обработают
|
||||||
|
|
||||||
class IR_Encoder;
|
class IR_Encoder;
|
||||||
class IR_Decoder : private IR_FOX {
|
class IR_Decoder : private IR_FOX {
|
||||||
friend IR_Encoder;
|
friend IR_Encoder;
|
||||||
@ -33,6 +35,8 @@ public:
|
|||||||
// @brief Для прерывания
|
// @brief Для прерывания
|
||||||
void isr();
|
void isr();
|
||||||
|
|
||||||
|
void tick();
|
||||||
|
|
||||||
|
|
||||||
// @return Буффер переполнился
|
// @return Буффер переполнился
|
||||||
bool isOverflow() { return isBufferOverflow; };
|
bool isOverflow() { return isBufferOverflow; };
|
||||||
@ -111,7 +115,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// class RawData : public Data {
|
// class RawData : public Data {
|
||||||
|
|
||||||
// };
|
// };
|
||||||
|
|
||||||
class Accept : public InputData {
|
class Accept : public InputData {
|
||||||
@ -175,7 +178,6 @@ private:
|
|||||||
bool isWaitingAccept = false;
|
bool isWaitingAccept = false;
|
||||||
uint16_t addrWaitingFrom = 0;
|
uint16_t addrWaitingFrom = 0;
|
||||||
|
|
||||||
|
|
||||||
uint16_t addrFrom = 0;
|
uint16_t addrFrom = 0;
|
||||||
|
|
||||||
uint16_t riseSyncTime = bitTime;
|
uint16_t riseSyncTime = bitTime;
|
||||||
@ -196,6 +198,26 @@ private:
|
|||||||
(bufferBitSizeMax / 8) + 1 :
|
(bufferBitSizeMax / 8) + 1 :
|
||||||
(bufferBitSizeMax / 8));
|
(bufferBitSizeMax / 8));
|
||||||
const uint8_t bufferDataSize = dataByteSizeMax; // + crc
|
const uint8_t bufferDataSize = dataByteSizeMax; // + crc
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
void noFunc();
|
||||||
|
volatile uint8_t currentFrontBufferWriteIndex;
|
||||||
|
struct FrontStorage {
|
||||||
|
volatile uint32_t time;
|
||||||
|
volatile bool dir;
|
||||||
|
volatile FrontStorage* next;
|
||||||
|
|
||||||
|
FrontStorage& operator= (FrontStorage& val) {
|
||||||
|
this->next = val.next;
|
||||||
|
this->time = val.time;
|
||||||
|
this->dir = val.dir;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
volatile FrontStorage* lastFront = nullptr;
|
||||||
|
volatile FrontStorage* firstUnHandledFront = nullptr;
|
||||||
|
volatile FrontStorage frontBuffer[subBuffer];
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
uint8_t* rawBuffer = nullptr;
|
uint8_t* rawBuffer = nullptr;
|
||||||
uint8_t* dataBuffer = nullptr;
|
uint8_t* dataBuffer = nullptr;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user