IR-protocol/IR_Decoder.h
2024-02-19 15:45:11 +03:00

131 lines
7.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "IR_config.h"
#include "IR_Output.h"
//#define IRDEBUG
#ifdef IRDEBUG
#define wrHigh A3 // Запись HIGH инициирована // green
#define wrLow A3 // Запись LOW инициирована // blue
#define writeOp 13 // Операция записи, 1 пульс для 0 и 2 для 1 // orange
// Исправленные ошибки // purle
// 1 пульс: fix
#define errOut A3
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////
#define riseTime riseSyncTime //* bitTime */ 893U // TODO: Должно высчитываться медианой
#define riseTolerance tolerance /* 250U */ // погрешность
#define riseTimeMax (riseTime + riseTolerance)
#define riseTimeMin (riseTime - riseTolerance)
#define aroundRise(t) (riseTimeMin < t && t < riseTimeMax)
#define IR_timeout (riseTimeMax * (8 + syncBits +1)) // us // таймаут в 8 data + 3 sync + 1
class IR_Encoder;
class IR_Decoder : private IR_FOX {
friend IR_Encoder;
public:
uint16_t id;
Data gotData; /// @brief Контейнер с данными
Data gotRawData;
Accept gotAccept; /// @brief Контейнер с подтверждением
Request gotRequest; /// @brief Контейнер с запросом
RawTune gotTune; /// @brief Контейнер с информацией подстройки
const uint8_t isrPin; // Пин прерывания
//////////////////////////////////////////////////////////////////////////
/// @brief Конструктор
/// @param isrPin Номер вывода прерывания/данных от приёмника (2 или 3 для atmega 328p)
/// @param addr Адрес приёмника
/// @param encPair Указатель на передатчик, работающий в паре
IR_Decoder(const uint8_t isrPin, uint16_t addr, IR_Encoder* encPair = nullptr);
~IR_Decoder();
void isr(); ///@brief Функция прерывания
void tick(); /// @brief Обработка приёмника, необходима для работы
// @return Буффер переполнился
bool isOverflow() { return isBufferOverflow; };
/// @brief Флаг приёма
/// @return Возвращает true, если происходит приём пакета
bool isReciving() { return isRecive; };
// @brief Слушатель для работы isReciving()
void listen();
//////////////////////////////////////////////////////////////////////////
private:
IR_Encoder* encoder; // Указатель на парный передатчик
volatile uint16_t isPairSending = 0; // Флаг передачи парного передатчика
volatile bool isRecive = false; // Флаг приёма
volatile bool isPreamb = false; // флаг начальной последовости
bool isWaitingAccept = false; // Флаг ожидания подтверждения
bool isCrcCorrect = false; // Флаг корректности crc
bool isBufferOverflow = false; // Флаг переполнения буффера данных
bool isWrongPack = false; // Флаг битого пакета
uint16_t addrWaitingFrom = 0; // Адрес, от кого ожидается подтверждение
uint16_t riseSyncTime = bitTime; // Подстраиваемое время бита в мкс
// bool HIGH_FIRST = true; //TODO: порядок приходящих битов
////////////////////////////////////////////////////////////////////////
volatile uint8_t currentSubBufferIndex; // Счетчик текущей позиции во вспомогательном буфере фронтов/спадов
struct FrontStorage { // Структура для хранения времени и направления фронта/спада
volatile uint32_t time = 0; // Время
volatile bool dir = false; // Направление (true = ↑; false = ↓)
volatile FrontStorage* next = nullptr; // Указатель на следующий связанный фронт/спад, или nullptr если конец
};
volatile FrontStorage* lastFront = nullptr; // Указатель последнего фронта/спада
volatile FrontStorage* firstUnHandledFront = nullptr; // Указатель первого необработанного фронта/спада
volatile FrontStorage subBuffer[subBufferSize]; // вспомогательный буфер для хранения необработанных фронтов/спадов
////////////////////////////////////////////////////////////////////////
uint8_t* dataBuffer = nullptr; // Указатель на буффер данных
uint32_t prevRise, prevPrevRise, prevFall, prevPrevFall; // Время предыдущих фронтов/спадов
uint16_t errorCounter = 0; // Счётчик ошибок
int8_t preambFrontCounter = 0; // Счётчик __/``` ↑ преамбулы
int16_t bufBitPos = 0; // Позиция для записи бита в буффер
private:
/// @brief Проверка CRC. Проверяет len байт со значением crc, пришедшим в пакете
/// @param len Длина в байтах проверяемых данных
/// @param crc Результат рассчёта crc (Выходной параметр)
/// @return true если crc верно
bool crcCheck(uint8_t len, uint16_t& crc);
////////////////////////////////////////////////////////////////////////
bool isData = true; // Флаг относится ли бит к данным, или битам синхронизации
uint16_t i_dataBuffer; // Счётчик буфера данных
uint8_t nextControlBit = bitPerByte; // Метка для смены флага isData
uint8_t i_syncBit; // Счётчик битов синхронизации
uint8_t err_syncBit; // Счётчик ошибок синхронизации
/// @brief Запиь бита в буффер, а так же проверка битов синхранизации и их фильтрация
/// @param Бит данных
void writeToBuffer(bool);
void packToOutClass(uint8_t endBitOffset, uint8_t bytesToCheck, uint8_t addressForCheckOffset, IDataPack* objFine, IDataPack* objWrong = nullptr);
////////////////////////////////////////////////////////////////////////
/// @brief Установка и сброс начальных значений и флагов в готовность к приёму данных
void start_RX();
/// @brief Целочисленное деление с округлением вверх
/// @param val Значение
/// @param divider Делитель
/// @return Результат
uint16_t ceil_div(uint16_t val, uint16_t divider);
#ifdef IRDEBUG
inline void errPulse(uint8_t pin, uint8_t count);
inline void infoPulse(uint8_t pin, uint8_t count);
#endif
};