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 {
|
||||
rawBuffer[(bufBitPos >> 3)] |= bit << (bufBitPos & ~(~0 << 3));
|
||||
} */
|
||||
|
||||
Serial.print(bit);
|
||||
#ifdef IRDEBUG
|
||||
bit ? infoPulse(writeOp, 2) : infoPulse(writeOp, 1);
|
||||
#endif
|
||||
@ -31,7 +31,7 @@ void IR_Decoder::writeToBuffer(bool bit) {
|
||||
if (isBufferOverflow) { //TODO: Буффер переполнен!
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//const auto testval = bufferBitSizeMax;
|
||||
if ((bufBitPos >= (8 * msgBytes) - syncBits) && !isMsgAvaliable) {
|
||||
switch ((rawBuffer[0] >> 5) & IR_MASK_MSG_TYPE) {
|
||||
@ -80,7 +80,7 @@ void IR_Decoder::writeToBuffer(bool bit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if (bufBitPos >= bufferRawSize * 8 - 1) { isBufferOverflow = true; }
|
||||
bufBitPos++;
|
||||
}
|
||||
@ -168,19 +168,27 @@ uint16_t IR_Decoder::ceil_div(uint16_t val, uint16_t divider) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void IR_Decoder::listen(){
|
||||
if(isRecive && micros()-prevRise > IR_timeout*2) {isRecive = false;}
|
||||
void IR_Decoder::listen() {
|
||||
if (isRecive && micros() - prevRise > IR_timeout * 2) {
|
||||
isRecive = false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////// isr ///////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IR_Decoder::tick() {
|
||||
if (firstUnHandledFront == nullptr) return; //Если данных нет - ничего не делаем
|
||||
|
||||
void IR_Decoder::isr() { // в прерывании вызываем isr()
|
||||
if (isPairSending) return;
|
||||
FrontStorage currentFront;
|
||||
//найти следующий необработанный фронт/спад
|
||||
noInterrupts();
|
||||
currentFront = *((FrontStorage*)firstUnHandledFront);
|
||||
interrupts();
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (micros() - prevRise > IR_timeout) { // первый
|
||||
if (currentFront.time - prevRise > IR_timeout && currentFront.dir) { // первый ↑
|
||||
isRecive = true;
|
||||
isPreamb = true;
|
||||
frontCounter = preambFronts - 1U;
|
||||
@ -188,6 +196,156 @@ void IR_Decoder::isr() { // в прерывании вызываем isr()
|
||||
riseSyncTime = bitTime /* 1100 */;
|
||||
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) { // в преамбуле
|
||||
uint32_t risePeriod = micros() - prevRise;
|
||||
@ -206,7 +364,7 @@ void IR_Decoder::isr() { // в прерывании вызываем isr()
|
||||
if (isPreamb) {// первый фронт после
|
||||
gotTune._set(riseSyncTime);
|
||||
}
|
||||
isPreamb = false;
|
||||
isPreamb = false;
|
||||
}
|
||||
|
||||
// определить направление фронта
|
||||
@ -325,6 +483,7 @@ void IR_Decoder::isr() { // в прерывании вызываем isr()
|
||||
#ifdef IRDEBUG
|
||||
digitalWrite(writeOp, isPreamb);
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
|
||||
|
26
IR_Decoder.h
26
IR_Decoder.h
@ -21,6 +21,8 @@
|
||||
#define aroundRise(t) (riseTimeMin < t && t < riseTimeMax)
|
||||
#define IR_timeout ((riseTimeMax * 8) + syncBits +1) // us // таймаут в 8 data + 3 sync + 1
|
||||
|
||||
#define subBuffer 5 //Буфер для складирования фронтов, пока их не обработают
|
||||
|
||||
class IR_Encoder;
|
||||
class IR_Decoder : private IR_FOX {
|
||||
friend IR_Encoder;
|
||||
@ -33,6 +35,8 @@ public:
|
||||
// @brief Для прерывания
|
||||
void isr();
|
||||
|
||||
void tick();
|
||||
|
||||
|
||||
// @return Буффер переполнился
|
||||
bool isOverflow() { return isBufferOverflow; };
|
||||
@ -111,7 +115,6 @@ public:
|
||||
};
|
||||
|
||||
// class RawData : public Data {
|
||||
|
||||
// };
|
||||
|
||||
class Accept : public InputData {
|
||||
@ -175,7 +178,6 @@ private:
|
||||
bool isWaitingAccept = false;
|
||||
uint16_t addrWaitingFrom = 0;
|
||||
|
||||
|
||||
uint16_t addrFrom = 0;
|
||||
|
||||
uint16_t riseSyncTime = bitTime;
|
||||
@ -196,6 +198,26 @@ private:
|
||||
(bufferBitSizeMax / 8) + 1 :
|
||||
(bufferBitSizeMax / 8));
|
||||
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* dataBuffer = nullptr;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user