STM works

This commit is contained in:
2024-04-22 11:20:53 +03:00
parent 03d74e30cd
commit e334625864
8 changed files with 381 additions and 274 deletions

View File

@ -15,55 +15,47 @@ IR_DecoderRaw::IR_DecoderRaw(const uint8_t isrPin, uint16_t addr, IR_Encoder *en
pinMode(wrLow, OUTPUT);
pinMode(writeOp, OUTPUT);
pinMode(errOut, OUTPUT);
pinMode(up, OUTPUT);
pinMode(down, OUTPUT);
#endif
}
//////////////////////////////////// isr ///////////////////////////////////////////
volatile uint32_t time_;
void IR_DecoderRaw::isr()
{
if (isPairSending)
return;
subBuffer[currentSubBufferIndex].next = nullptr;
subBuffer[currentSubBufferIndex].dir = digitalRead(isrPin);
subBuffer[currentSubBufferIndex].time = micros();
if (firstUnHandledFront == nullptr)
noInterrupts();
// time_ = HAL_GetTick() * 1000 + ((SysTick->LOAD + 1 - SysTick->VAL) * 1000) / SysTick->LOAD + 1;
time_ = micros();
interrupts();
if (time_ < oldTime)
{
firstUnHandledFront = &subBuffer[currentSubBufferIndex]; // Если нет необработанных данных - добавляем их
isSubBufferOverflow = false;
}
else
{
if (firstUnHandledFront == &subBuffer[currentSubBufferIndex])
{ // Если контроллер не успел обработать новый сигнал, принудительно пропускаем его
firstUnHandledFront = firstUnHandledFront->next;
isSubBufferOverflow = true;
#ifdef IRDEBUG_INFO
// Serial.println();
Serial.println(" ISR BUFFER OVERFLOW ");
// Serial.println();
#ifdef IRDEBUG
Serial.print("\n");
Serial.print("count: ");
Serial.println(wrongCounter++);
Serial.print("time: ");
Serial.println(time_);
Serial.print("oldTime: ");
Serial.println(oldTime);
Serial.print("sub: ");
Serial.println(max((uint32_t)time_, oldTime) - min((uint32_t)time_, oldTime));
#endif
}
time_ += 1000;
}
oldTime = time_;
if (lastFront == nullptr)
{
lastFront = &subBuffer[currentSubBufferIndex];
}
else
{
lastFront->next = &subBuffer[currentSubBufferIndex];
lastFront = &subBuffer[currentSubBufferIndex];
}
FrontStorage edge;
edge.dir = digitalRead(isrPin);
edge.time = time_;
currentSubBufferIndex == (subBufferSize - 1) ? currentSubBufferIndex = 0 : currentSubBufferIndex++; // Закольцовка буффера
subBuffer.push(edge);
}
////////////////////////////////////////////////////////////////////////////////////
uint32_t wrCounter;
void IR_DecoderRaw::firstRX()
{
@ -86,6 +78,8 @@ void IR_DecoderRaw::firstRX()
isPreamb = true;
riseSyncTime = bitTime /* 1100 */;
wrCounter = 0;
memset(dataBuffer, 0x00, dataByteSizeMax);
}
@ -98,56 +92,116 @@ void IR_DecoderRaw::listenStart()
firstRX();
}
}
void IR_DecoderRaw::tick()
{
FrontStorage currentFront;
noInterrupts();
listenStart();
if (firstUnHandledFront == nullptr)
FrontStorage *currentFrontPtr;
currentFrontPtr = subBuffer.pop();
if (currentFrontPtr == nullptr)
{
isSubBufferOverflow = false;
interrupts();
return;
} // Если данных нет - ничего не делаем
currentFront = *((FrontStorage *)firstUnHandledFront); // найти следующий необработанный фронт/спад
} // Если данных нет - ничего не делаем
currentFront = *currentFrontPtr;
interrupts();
if (currentFront.next == nullptr)
{
isRecive = false;
return;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (currentFront.dir)
{ // Если __/``` ↑
if (currentFront.time - prevRise > riseTimeMax / 2 || highCount || lowCount)
{ // комплексный фикс рваной единицы
risePeriod = currentFront.time - prevRise;
highTime = currentFront.time - prevFall;
lowTime = prevFall - prevRise;
prevRise = currentFront.time;
if (
risePeriod > UINT32_MAX - IR_timeout * 10 ||
highTime > UINT32_MAX - IR_timeout * 10 ||
lowTime > UINT32_MAX - IR_timeout * 10 ||
prevRise > UINT32_MAX - IR_timeout * 10)
{
#ifdef IRDEBUG
errPulse(down, 50);
// Serial.print("\n");
// Serial.print("risePeriod: ");
// Serial.println(risePeriod);
// Serial.print("highTime: ");
// Serial.println(highTime);
// Serial.print("lowTime: ");
// Serial.println(lowTime);
// Serial.print("prevRise: ");
// Serial.println(prevRise);
#endif
}
}
else
{
errors.other++;
}
}
else
{ // Если ```\__ ↓
if (currentFront.time - prevFall > riseTimeMin / 4)
{
prevFall = currentFront.time;
}
else
{
errors.other++;
}
}
#ifdef IRDEBUG
// goto END; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#endif
//----------------------------------------------------------------------------------
#ifdef IRDEBUG
digitalWrite(errOut, currentFront.dir);
#endif
if (currentFront.time > prevRise && currentFront.time - prevRise > IR_timeout * 2 && !isRecive)
{ // первый
preambFrontCounter = preambFronts - 1U;
if (!currentFront.dir)
{
#ifdef IRDEBUG_INFO
// Serial.print(" currentFront.time: "); Serial.print(currentFront.time);
// Serial.print(" currentFront.dir: "); Serial.print(currentFront.dir ? "UP" : "DOWN");
// Serial.print(" next: "); Serial.print(currentFront.next == nullptr);
// Serial.print(" prevRise: "); Serial.print(prevRise);
// Serial.print(" SUB: "); Serial.println(currentFront.time - prevRise);
#ifdef IRDEBUG
errPulse(up, 50);
errPulse(down, 50);
errPulse(up, 150);
errPulse(down, 150);
#endif
isRecive = true;
isWrongPack = false;
}
preambFrontCounter = preambFronts - 1U;
isPreamb = true;
isRecive = true;
isWrongPack = false;
}
//-------------------------------------------------------------------------------------------------------
if (preambFrontCounter)
{ // в преамбуле
uint32_t risePeriod;
risePeriod = currentFront.time - prevRise;
#ifdef IRDEBUG
Serial.print("risePeriod: ");
Serial.println(risePeriod);
#endif
if (currentFront.dir && risePeriod < IR_timeout)
{ // __/``` ↑ и мы в внутри пакета
if (risePeriod < riseTimeMin << 1)
if (risePeriod < riseTimeMin / 2)
{ // fix рваной единицы
preambFrontCounter += 2;
errors.other++;
#ifdef IRDEBUG
errPulse(down, 350);
#endif
}
else
{
@ -168,194 +222,182 @@ void IR_DecoderRaw::tick()
if (isPreamb)
{ // первый фронт после
// gotTune.set(riseSyncTime);
isPreamb = false;
#ifdef IRDEBUG
errPulse(up, 50);
errPulse(down, 50);
#endif
prevRise += risePeriod / 2;
// prevRise = currentFront.time + riseTime;
goto END;
}
isPreamb = false;
}
if (isPreamb)
{
goto END;
}
if (risePeriod > IR_timeout || isBufferOverflow || risePeriod < riseTimeMin || isWrongPack)
// ~Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц
{
goto END;
}
// определить направление фронта
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;
highCount = 0;
lowCount = 0;
allCount = 0;
bool invertErr = false;
if (!isPreamb)
{
if (risePeriod < IR_timeout && !isBufferOverflow && risePeriod > riseTimeMin && !isWrongPack)
{
// Мы в пределах таймаута и буффер не переполнен и fix дроблёных единиц
if (aroundRise(risePeriod))
{ // тактирование есть, сигнал хороший - без ошибок(?)
if (highTime > riseTimeMin / 2U)
{ // 1
#ifdef IRDEBUG
digitalWrite(wrHigh, 1);
#endif
writeToBuffer(HIGH);
}
else
{ // 0
#ifdef IRDEBUG
digitalWrite(wrLow, 1);
#endif
writeToBuffer(LOW);
}
}
else
{ // пропущены такты! сигнал средний // ошибка пропуска
highCount = ceil_div(highTime, riseTime); // предполагаемое колличество HIGH битов
lowCount = ceil_div(lowTime, riseTime); // предполагаемое колличество LOW битов
allCount = ceil_div(risePeriod, riseTime); // предполагаемое колличество всего битов
Serial.print("\n");
if (highCount == 0 && highTime > riseTime / 3)
{ // fix короткой единицы (?)после пропуска нулей(?)
highCount++;
errors.other++;
#ifdef IRDEBUG
errPulse(errOut, 2);
#endif
}
Serial.print("wrCounter: ");
Serial.println(wrCounter++);
if (lowCount + highCount > allCount)
{ // fix ошибочных сдвигов
if (lowCount > highCount)
{ // Лишние нули
lowCount = allCount - highCount;
errors.lowSignal += lowCount;
#ifdef IRDEBUG
errPulse(errOut, 3);
#endif
}
else if (lowCount < highCount)
{ // Лишние единицы
highCount = allCount - lowCount;
errors.highSignal += highCount;
#ifdef IRDEBUG
errPulse(errOut, 4);
#endif
// неизвестный случай Инверсит след бит или соседние
// Очень редко
// TODO: Отловить проверить
}
else if (lowCount == highCount)
{
invertErr = true;
// Serial.print("...");
errors.other += allCount;
}
// errorCounter += allCount;
}
Serial.print("risePeriod: ");
Serial.println(risePeriod);
// errorCounter += allCount;
// errors.other+=allCount;
if (lowCount < highCount)
{
errors.highSignal += highCount;
}
else
{
errors.lowSignal += lowCount;
}
Serial.print("highTime: ");
Serial.println(highTime);
#ifdef IRDEBUG
errPulse(errOut, 1);
Serial.print("lowTime: ");
Serial.println(lowTime);
#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
}
}
if (aroundRise(risePeriod))
{ // тактирование есть, сигнал хороший - без ошибок(?)
for (int8_t i = 0; i < highCount && 8 - i; i++)
{ // отправка HIGH битов, если есть
if (i == highCount - 1 && invertErr)
{
invertErr = false;
writeToBuffer(!HIGH);
if (highTime > lowTime)
{ // 1
#ifdef IRDEBUG
digitalWrite(wrLow, 1);
errPulse(wrHigh, 1);
#endif
}
else
{
writeToBuffer(HIGH);
writeToBuffer(HIGH);
}
else
{ // 0
#ifdef IRDEBUG
digitalWrite(wrHigh, 1);
#endif
}
}
}
#ifdef IRDEBUG
digitalWrite(wrHigh, 0);
digitalWrite(wrLow, 0);
errPulse(wrLow, 1);
#endif
writeToBuffer(LOW);
}
}
if (risePeriod > riseTimeMax / 2 || highCount || lowCount)
{ // комплексный фикс рваной единицы
prevPrevRise = prevRise;
prevRise = currentFront.time;
}
else
{
errors.other++;
{ // пропущены такты! сигнал средний // ошибка пропуска
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++;
errors.other++;
#ifdef IRDEBUG
errPulse(errOut, 5);
errPulse(up, 50);
#endif
}
if (lowCount + highCount > allCount)
{ // fix ошибочных сдвигов
if (lowCount > highCount)
{ // Лишние нули
lowCount = allCount - highCount;
errors.lowSignal += lowCount;
#ifdef IRDEBUG
// errPulse(errOut, 3);
errPulse(down, 40);
errPulse(up, 10);
errPulse(down, 40);
#endif
}
else if (lowCount < highCount)
{ // Лишние единицы
highCount = allCount - lowCount;
errors.highSignal += highCount;
#ifdef IRDEBUG
errPulse(down, 10);
errPulse(up, 40);
errPulse(down, 10);
// errPulse(errOut, 4);
#endif
// неизвестный случай Инверсит след бит или соседние
// Очень редко
// TODO: Отловить проверить
}
else if (lowCount == highCount)
{
#ifdef IRDEBUG
errPulse(down, 40);
errPulse(up, 40);
errPulse(down, 40);
#endif
invertErr = true;
// Serial.print("...");
errors.other += allCount;
}
// errorCounter += allCount;
}
// errorCounter += allCount;
// errors.other+=allCount;
if (lowCount < highCount)
{
errors.highSignal += highCount;
}
else
{
errors.lowSignal += lowCount;
}
// errPulse(errOut, 1);
for (int8_t i = 0; i < lowCount && 8 - i; i++)
{ // отправка LOW битов, если есть
if (i == lowCount - 1 && invertErr)
{
invertErr = false;
writeToBuffer(HIGH);
#ifdef IRDEBUG
errPulse(wrHigh, 1);
#endif
}
else
{
writeToBuffer(LOW);
#ifdef IRDEBUG
errPulse(wrLow, 1);
#endif
}
}
for (int8_t i = 0; i < highCount && 8 - i; i++)
{ // отправка HIGH битов, если есть
if (i == highCount - 1 && invertErr)
{
invertErr = false;
writeToBuffer(LOW);
#ifdef IRDEBUG
errPulse(wrLow, 1);
#endif
}
else
{
writeToBuffer(HIGH);
#ifdef IRDEBUG
errPulse(wrHigh, 1);
#endif
}
}
}
}
else
{ // Если ```\__ ↓
if (currentFront.time - prevFall > riseTimeMin)
{
prevPrevFall = prevFall;
prevFall = currentFront.time;
}
else
{
#ifdef IRDEBUG
// errPulse(errOut, 5);
#endif
}
}
if (isPreamb && preambFrontCounter <= 0)
{
prevRise = currentFront.time + riseTime;
}
#ifdef IRDEBUG
digitalWrite(writeOp, isPreamb);
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// noInterrupts();
if (firstUnHandledFront != nullptr)
{
firstUnHandledFront = firstUnHandledFront->next; // переместить флаг на следующий элемент для обработки (next or nullptr)
}
// interrupts();
////////////////////////////////////////////////////////////////////////////////////////////////////////////
END:;
}
void IR_DecoderRaw::writeToBuffer(bool bit)
@ -484,7 +526,7 @@ void IR_DecoderRaw::writeToBuffer(bool bit)
if (packSize && (i_dataBuffer == packSize * bitPerByte))
{ // Конец
#ifdef IRDEBUG_INFO
Serial.print(" END DATA ");
Serial.print(" END DATA " + crcCheck(packSize - crcBytes, crcValue) ? "OK " : "ERR ");
#endif
packInfo.buffer = dataBuffer;
@ -496,35 +538,33 @@ void IR_DecoderRaw::writeToBuffer(bool bit)
isRecive = false;
isAvailable = crcCheck(packSize - crcBytes, crcValue);
if (!isAvailable) // Исправление первого бита // Очень большая затычка...
for (size_t i = 0; i < packSize; ++i)
{
for (int j = 0; j < 8; ++j)
#ifdef BRUTEFORCE_CHECK
if (!isAvailable) // Исправление первого бита // Очень большая затычка...
for (size_t i = 0; i < min(packSize - crcBytes*2, dataByteSizeMax); ++i)
{
// инвертируем бит
dataBuffer[i] ^= 1 << j;
isAvailable = crcCheck(packSize - crcBytes, crcValue);
// обратно инвертируем бит в исходное состояние
if (isAvailable)
{
#ifdef IRDEBUG_INFO
Serial.println("!!!INV!!!");
#endif
goto OUT_BRUTEFORCE;
}
else
for (int j = 0; j < 8; ++j)
{
// инвертируем бит
dataBuffer[i] ^= 1 << j;
isAvailable = crcCheck(packSize - crcBytes, crcValue);
// обратно инвертируем бит в исходное состояние
if (isAvailable)
{
#ifdef IRDEBUG_INFO
Serial.println("!!!INV!!!");
#endif
goto OUT_BRUTEFORCE;
}
else
{
dataBuffer[i] ^= 1 << j;
}
}
}
}
OUT_BRUTEFORCE:;
// {
// dataBuffer[0] |= 0b10000000;
// isAvailable = crcCheck(packSize - crcBytes, crcValue);
// }
OUT_BRUTEFORCE:;
#endif
}
}