diff --git a/IR_Decoder.cpp b/IR_Decoder.cpp index f9257e6..29a3830 100644 --- a/IR_Decoder.cpp +++ b/IR_Decoder.cpp @@ -4,11 +4,11 @@ #define IRDEBUG_INFO #define checkAddr(h, l) (\ - ((uint16_t)((dataBuffer[h] << 8) | dataBuffer[l]) == addrSelf) || \ + ((uint16_t)((dataBuffer[h] << 8) | dataBuffer[l]) == id) || \ ((uint16_t)((dataBuffer[h] << 8) | dataBuffer[l]) >= IR_Broadcast)\ ) -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), id(addr), encoder(encPair) { // rawBuffer = new uint8_t[bufferRawSize] { 0 }; dataBuffer = new uint8_t[dataByteSizeMax] { 0 }; prevRise = prevFall = prevPrevFall = prevPrevRise = 0; @@ -124,7 +124,7 @@ void IR_Decoder::tick() { // Serial.print("preambFrontCounter: "); Serial.println(preambFrontCounter); } else { if (isPreamb) {// первый фронт после - gotTune._set(riseSyncTime); + gotTune.set(dataBuffer, 1, 0, errors, riseSyncTime); } isPreamb = false; } @@ -367,7 +367,7 @@ void IR_Decoder::writeToBuffer(bool bit) { packToOutClass( ((msgBytes + addrBytes + crcBytes) * bitPerByte), // endBitOffset (msgBytes + addrBytes), // bytesToCheck - 1, // addressForCheckOffset + 1, // addressForCheck_Offset &gotAccept // objFine ); break; @@ -376,7 +376,7 @@ void IR_Decoder::writeToBuffer(bool bit) { packToOutClass( ((msgBytes + addrBytes + addrBytes + crcBytes) * bitPerByte), // endBitOffset (msgBytes + addrBytes + addrBytes), // bytesToCheck - 3, // addressForCheckOffset + 3, // addressForCheck_Offset &gotRequest // objFine ); break; @@ -387,7 +387,7 @@ void IR_Decoder::writeToBuffer(bool bit) { packToOutClass( (((dataBuffer[0] & IR_MASK_MSG_INFO) + crcBytes) * bitPerByte), // endBitOffset (dataBuffer[0] & IR_MASK_MSG_INFO), // bytesToCheck - 3, // addressForCheckOffset + 3, // addressForCheck_Offset &gotData, // objFine &gotRawData // objWrong ); @@ -400,9 +400,9 @@ void IR_Decoder::writeToBuffer(bool bit) { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } -void IR_Decoder::packToOutClass(uint8_t endBitOffset, uint8_t bytesToCheck, uint8_t addressForCheckOffset, InputData* objFine, InputData* objWrong = nullptr) { +void IR_Decoder::packToOutClass(uint8_t endBitOffset, uint8_t bytesToCheck, uint8_t addressForCheckOffset, IDataPack* objFine, IDataPack* objWrong = nullptr) { uint16_t crcValue; - InputData* objResult = nullptr; + IDataPack* objResult = nullptr; if (i_dataBuffer == endBitOffset) { #ifdef IRDEBUG_INFO Serial.print(" IN "); @@ -420,8 +420,8 @@ void IR_Decoder::packToOutClass(uint8_t endBitOffset, uint8_t bytesToCheck, uint #endif } if (objWrong != nullptr) { - objResult->_isAvaliable = true; - objResult->_set(dataBuffer, bytesToCheck + crcBytes, crcValue, errors, riseSyncTime); + objResult->isAvaliable = true; + objResult->set(dataBuffer, bytesToCheck + crcBytes, crcValue, errors, riseSyncTime); } isRecive = false; } @@ -442,7 +442,9 @@ bool IR_Decoder::crcCheck(uint8_t len, crc_t& crc) { dataBuffer[len + 1] == (crc & 0xFF) ) { crcOK = true; - } else { crcOK = false; } + } else { + crcOK = false; + } return crcOK; diff --git a/IR_Decoder.h b/IR_Decoder.h index 4a36fb1..b7ad346 100644 --- a/IR_Decoder.h +++ b/IR_Decoder.h @@ -1,5 +1,6 @@ #pragma once #include "IR_config.h" +#include "IR_Output.h" //#define IRDEBUG @@ -26,182 +27,55 @@ class IR_Encoder; class IR_Decoder : private IR_FOX { friend IR_Encoder; public: - uint16_t addrSelf; + 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(); - // @brief Функция прерывания - void isr(); - - /// @brief Обработка приёмника, необходима для работы - void tick(); - + void isr(); ///@brief Функция прерывания + void tick(); /// @brief Обработка приёмника, необходима для работы // @return Буффер переполнился bool isOverflow() { return isBufferOverflow; }; + /// @brief Флаг приёма /// @return Возвращает true, если происходит приём пакета bool isReciving() { return isRecive; }; + // @brief Слушатель для работы isReciving() void listen(); ////////////////////////////////////////////////////////////////////////// - - -public: - class InputData : protected IR_FOX { - friend IR_Decoder; - protected: - bool _isAvaliable = false; - uint8_t _msgType = 0; - uint16_t _addrFrom = 0; - uint16_t _addrTo = 0; - uint8_t _data[dataByteSizeMax]; - uint8_t _dataRawSize = 0; - uint16_t _crcPackVal = 0; - uint16_t _crcCalcVal = 0; - ErrorsStruct _err; - uint16_t _bitPeriod = 0; - - void _set(uint8_t* ptr, uint8_t len, uint16_t crc, ErrorsStruct err, uint16_t rTime) { - _crcCalcVal = crc; - _dataRawSize = len; - _err = err; - _bitPeriod = rTime; - memset(_data, 0, dataByteSizeMax); - memcpy(_data, ptr, min(len, dataByteSizeMax)); - _msgType = _data[0]; - ini(); - _isAvaliable = true; - } - - private: - virtual void ini(); - - public: - bool avaliable() { return _isAvaliable; }; - uint8_t msgInfo() { return _msgType & IR_MASK_MSG_INFO; }; - uint8_t msgType() { return (_msgType >> 5) & IR_MASK_MSG_TYPE; }; - uint8_t msgRAW() { return _msgType; }; - uint16_t errorCount() { return _err.all(); }; - uint8_t errorLowSignal() { return _err.lowSignal; }; - uint8_t errorHighSignal() { return _err.highSignal; }; - uint8_t errorOther() { return _err.other; }; - uint16_t crcIN() { return _crcPackVal; }; - uint16_t crcCALC() { return _crcCalcVal; }; - uint16_t tunerTime() { return _bitPeriod; }; - void resetAvaliable() { _isAvaliable = false; }; - }; - - ////////////////////////////////////////////////////////////////////////// - - class Data : public InputData { - public: - uint16_t addrFrom() { return _addrFrom; }; - uint16_t addrTo() { return _addrTo; }; - uint8_t dataSize() { return _dataRawSize - (msgBytes + addrBytes + addrBytes + crcBytes); }; - uint8_t* data() { return &_data[msgBytes + addrBytes + addrBytes]; }; - uint8_t dataRawSize() { return _dataRawSize; }; - uint8_t* dataRaw() { return _data; }; - bool isNeedAccept() { return ((_msgType >> 5) & IR_MASK_MSG_TYPE) == IR_MSG_DATA_ACCEPT; }; - // String printRawData(uint8_t mode = 10) { - // return printBytes(dataRaw(), dataRawSize(), mode); - // } - // String printData(uint8_t mode = 10) { - // return printBytes(data(), dataSize(), mode); - // } - ~Data() {}; - private: - void ini() override { - _addrFrom = (_data[1] << 8) | _data[2]; - _addrTo = (_data[3] << 8) | _data[4]; - _crcPackVal = (_data[_dataRawSize - 2] << 8) | _data[_dataRawSize - 1]; - } - }; - - // class RawData : public Data { - // }; - - class Accept : public InputData { - public: - uint16_t addrFrom() { return _addrFrom; }; - - private: - void ini() override { - _addrFrom = (_data[1] << 8) | _data[2]; - _crcPackVal = (_data[3] << 8) | _data[4]; - } - }; - - class Request : public Accept { - public: - uint16_t addrTo() { return _addrTo; }; - private: - void ini() override { - _addrFrom = (_data[1] << 8) | _data[2]; - _addrTo = (_data[3] << 8) | _data[4]; - _crcPackVal = (_data[5] << 8) | _data[6]; - } - }; - - class RawTune { - friend IR_Decoder; - private: - bool _isAvaliable = false; - uint16_t _errCount = 0; - uint16_t _tune = 0; - public: - bool avaliable() { return _isAvaliable; }; - uint16_t getTune() { return _tune; }; - uint16_t errorCount() { return _errCount; }; - void resetAvaliable() { _isAvaliable = false; }; - private: - void _set(uint16_t val) { - _tune = val; - _isAvaliable = true; - } - }; - - /// @brief Контейнер с данными - Data gotData; - Data gotRawData; - /// @brief Контейнер с подтверждением - Accept gotAccept; - /// @brief Контейнер с запросом - Request gotRequest; - /// @brief Контейнер с информацией подстройки - RawTune gotTune; - - const uint8_t isrPin; // Пин прерывания - private: - - IR_Encoder* encoder; // Указатель на парный передатчик volatile uint16_t isPairSending = 0; // Флаг передачи парного передатчика - - volatile bool isRecive = false; // Флаг приёма - + volatile bool isPreamb = false; // флаг начальной последовости bool isWaitingAccept = false; // Флаг ожидания подтверждения - uint16_t addrWaitingFrom = 0; // Адрес, от кого ожидается подтверждение - - uint16_t riseSyncTime = bitTime; // Подстраиваемое время бита в мкс - bool isCrcCorrect = false; // Флаг корректности crc bool isBufferOverflow = false; // Флаг переполнения буффера данных bool isWrongPack = false; // Флаг битого пакета - volatile bool isPreamb = false; // флаг начальной последовости - bool HIGH_FIRST = true; //TODO: порядок приходящих битов + uint16_t addrWaitingFrom = 0; // Адрес, от кого ожидается подтверждение + uint16_t riseSyncTime = bitTime; // Подстраиваемое время бита в мкс + + // bool HIGH_FIRST = true; //TODO: порядок приходящих битов //////////////////////////////////////////////////////////////////////// - void noFunc(); volatile uint8_t currentSubBufferIndex; // Счетчик текущей позиции во вспомогательном буфере фронтов/спадов struct FrontStorage { // Структура для хранения времени и направления фронта/спада @@ -225,6 +99,7 @@ private: /// @param crc Результат рассчёта crc (Выходной параметр) /// @return true если crc верно bool crcCheck(uint8_t len, uint16_t& crc); + //////////////////////////////////////////////////////////////////////// bool isData = true; // Флаг относится ли бит к данным, или битам синхронизации uint16_t i_dataBuffer; // Счётчик буфера данных @@ -235,13 +110,12 @@ private: /// @brief Запиь бита в буффер, а так же проверка битов синхранизации и их фильтрация /// @param Бит данных void writeToBuffer(bool); - void packToOutClass(uint8_t endBitOffset, uint8_t bytesToCheck, uint8_t addressForCheckOffset, InputData* objFine, InputData* objWrong = nullptr); + 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 Делитель @@ -254,4 +128,4 @@ private: #endif -}; \ No newline at end of file + }; \ No newline at end of file diff --git a/IR_Output.h b/IR_Output.h new file mode 100644 index 0000000..9a79ce7 --- /dev/null +++ b/IR_Output.h @@ -0,0 +1,133 @@ +#pragma once +#include "IR_config.h" +class IR_Decoder; + +class IDataPack : protected IR_FOX { + friend IR_Decoder; +protected: + inline static uint8_t data[dataByteSizeMax]{0}; + + bool isAvaliable = false; + + void* msgPtr = nullptr; + void* addrFromPtr = nullptr; + void* addrToPtr = nullptr; + void* dataPtr = nullptr; + void* crcPtr = nullptr; + + + + uint8_t msgByte = 0; + uint8_t packRawSize = 0; // полная длина пакета + + ErrorsStruct err; + uint16_t bitPeriod = 0; + uint16_t crcPackVal = 0; + uint16_t crcCalcVal = 0; + + ///////////// смещения //////////////// + uint8_t crcOffset; + //переопределяемые дочерними классами// + uint8_t msgOffset; + uint8_t addrFromOffset; + uint8_t addrToOffset; + uint8_t dataOffset; + ////////////////////////////////////// + + void set(uint8_t* ptr, uint8_t len, uint16_t crc, ErrorsStruct err, uint16_t rTime) { + memset(IDataPack::data, 0, dataByteSizeMax); + memcpy(data, ptr, min(len, dataByteSizeMax)); + packRawSize = len; + + bitPeriod = rTime; + err = err; + crcCalcVal = crc; + crcOffset = packRawSize - crcBytes; + + msgByte = *(uint8_t*)msgPtr; + isAvaliable = true; + + msgPtr = (data + msgOffset); + addrFromPtr = (data + addrFromOffset); + addrToPtr = (data + addrToOffset); + dataPtr = (data + dataOffset); + crcPtr = (data + crcOffset); + + } + +public: + bool avaliable() { return isAvaliable; }; + uint8_t getMsgInfo() { return msgByte & IR_MASK_MSG_INFO; }; + uint8_t getMsgType() { return (msgByte >> 5) & IR_MASK_MSG_TYPE; }; + uint8_t getMsgRAW() { return msgByte; }; + uint16_t getErrorCount() { return err.all(); }; + uint8_t getErrorLowSignal() { return err.lowSignal; }; + uint8_t getErrorHighSignal() { return err.highSignal; }; + uint8_t getErrorOther() { return err.other; }; + uint16_t getTunerTime() { return bitPeriod; }; + void resetAvaliable() { isAvaliable = false; }; +}; + +////////////////////////////////////////////////////////////////////////// + +class Data : public IDataPack { +public: + Data() { + msgOffset = 0; + addrFromOffset = 1; + addrToOffset = 3; + dataOffset = 5; + + } + + +public: + uint16_t getAddrFrom() { return *(uint16_t*)addrFromPtr; }; + uint16_t getAddrTo() { return *(uint16_t*)addrToPtr; }; + uint8_t getDataSize() { return packRawSize - (msgBytes + addrBytes + addrBytes + crcBytes); }; + uint8_t* getDataPrt() { return (uint8_t*)dataPtr; }; + uint8_t getDataRawSize() { return packRawSize; }; + uint8_t* getDataRawPtr() { return data; }; + uint16_t getCrcIN() { return *(uint16_t*)crcPtr; }; + uint16_t getCrcCALC() { return crcCalcVal; }; + bool isNeedAccept() { return ((msgByte >> 5) & IR_MASK_MSG_TYPE) == IR_MSG_DATA_ACCEPT; }; + ~Data() {}; +}; + +// class RawData : public Data { +// }; + +class Accept : public IDataPack { +public: + Accept() { + msgOffset = 0; + addrFromOffset = 1; + } + + uint16_t getAddrFrom() { return *(uint16_t*)addrFromPtr; }; + uint16_t getCrcIN() { return *(uint16_t*)crcPtr; }; + uint16_t getCrcCALC() { return crcCalcVal; }; + +}; + +class Request : public IDataPack { +public: + Request() { + msgOffset = 0; + addrFromOffset = 1; + addrToOffset = 3; + } + + uint16_t getAddrFrom() { return *(uint16_t*)addrFromPtr; }; + uint16_t getAddrTo() { return *(uint16_t*)addrToPtr; }; + uint16_t getCrcIN() { return *(uint16_t*)crcPtr; }; + uint16_t getCrcCALC() { return crcCalcVal; }; +}; + +class RawTune : public IDataPack { +public: + RawTune() { + msgOffset = 0; + } + +}; \ No newline at end of file diff --git a/IR_config.h b/IR_config.h index 368a77f..a106116 100644 --- a/IR_config.h +++ b/IR_config.h @@ -22,10 +22,10 @@ IR_MSG_ACCEPT с адреса 0 воспринимается всеми устр /```````````````````````````````````````````````` data pack `````````````````````````````````````````````\                                                                                                                                             {``````````} [````````````````````````] [````````````````````] [````````````````````````] [``````````````] -{ msg type } [ addr_self uint16_t ] [ addr_to uint16_t ] [====== data bytes ======] [ CRC Bytes ] +{ msg type } [ addr_from uint16_t ] [ addr_to uint16_t ] [====== data bytes ======] [ CRC Bytes ] {..........} [........................] [....................] [........................] [..............]                                                                                                            -{ aka size } [addr_self_H][addr_self_L] [addr_to_H][addr_to_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ] +{ aka size } [addr_from_H][addr_from_L] [addr_to_H][addr_to_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ] |     0           1            2              3         4          5                         |       |     \____________________________________________________________________________________________/       |     |                                                                                                    |     @@ -55,10 +55,10 @@ msg type: /```````````````````` подтверждение ```````````````````\      /``````````````````````````````````````` запрос ``````````````````````````````````\                                                                                                                        {``````````} [````````````````````````] [``````````````]      {``````````} [````````````````````````] [````````````````````````] [``````````````] -{ msg type } [ addr_self uint16_t ] [ CRC Bytes ]      { msg type } [ addr_self uint16_t ] [ addr_to uint16_t ] [ CRC Bytes ] +{ msg type } [ addr_from uint16_t ] [ CRC Bytes ]      { msg type } [ addr_from uint16_t ] [ addr_to uint16_t ] [ CRC Bytes ] {..........} [........................] [..............]      {..........} [........................] [........................] [..............]                                                                                                                                                   -{ 001..... } [addr_self_H][addr_self_L] [ crc1 ][ crc2 ]      { 010..... } [addr_self_H][addr_self_L] [addr_self_H][addr_self_L] [ crc1 ][ crc2 ] +{ 001..... } [addr_from_H][addr_from_L] [ crc1 ][ crc2 ]      { 010..... } [addr_from_H][addr_from_L] [addr_from_H][addr_from_L] [ crc1 ][ crc2 ] |     0            1           2           3       4          |     0            1           2              3           4           5       6     \__________________________________________/       |          \_____________________________________________________________________/       |     |                                                  |          |                                                                             |     @@ -69,10 +69,10 @@ msg type: /`````````````````````` Задний сигнал машинки без адресации ``````````````````````\        В (IR_MASK_MSG_INFO & 15U) содержится количество байт                                                                                            сквозных команд, максимум 15 {``````````} [````````````````````````] [````````````````````````] [``````````````]        Если полезных байт информации нет, отправляется один -{ msg type } [ addr_self uint16_t ] [====== data bytes ======] [ CRC Bytes ]        байт нулей +{ msg type } [ addr_from uint16_t ] [====== data bytes ======] [ CRC Bytes ]        байт нулей {..........} [........................] [........................] [..............]                                                                                                     -{ 0000xxxx } [addr_self_H][addr_self_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ]         +{ 0000xxxx } [addr_from_H][addr_from_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ]         |     0           1            2            3                         |       |             \_____________________________________________________________________/       |             |                                                                             |             @@ -83,10 +83,10 @@ msg type: /```````````````````````````````````` Задний сигнал машинки с адресацией ````````````````````````````````````\                                                                                       {``````````} [````````````````````````] [````````````````````````] [````````````````````````] [``````````````]  -{ msg type } [ addr_self uint16_t ] [ addr_to uint16_t ] [====== data bytes ======] [ CRC Bytes ]  +{ msg type } [ addr_from uint16_t ] [ addr_to uint16_t ] [====== data bytes ======] [ CRC Bytes ]  {..........} [........................] [........................] [........................] [..............]                                                                                                                  -{ 0001xxxx } [addr_self_H][addr_self_L] [addr_self_H][addr_self_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ]  +{ 0001xxxx } [addr_from_H][addr_from_L] [addr_from_H][addr_from_L] [data_H][data_n..][data_L] [ crc1 ][ crc2 ]  |     0           1            2              3           4            5                         |       |      \________________________________________________________________________________________________/       |      |                                                                                                        |