#pragma once #include "IR_config.h" //TODO: Отложенная передача после завершения приема class IR_Decoder; class IR_Encoder : IR_FOX { friend IR_Decoder; friend void isr(IR_Encoder& e); public: uint8_t ir_out; /// @brief Вывод передатчика uint16_t id; /// @brief Адрес передатчика private: public: /// @brief Класс передатчика /// @param addr Адрес передатчика /// @param pin Вывод передатчика /// @param tune Подстройка несущей частоты /// @param decPair Приёмник, для которого отключается приём в момент передачи передатчиком IR_Encoder(uint16_t addr, uint8_t pin, IR_Decoder* decPair = nullptr); void IR_Encoder::setBlindDecoders(IR_Decoder* decoders[], uint8_t count); template void sendData(uint16_t addrTo, T& data, bool needAccept = false); void sendData(uint16_t addrTo, uint8_t* data, uint8_t len, bool needAccept = false); void sendACK(uint16_t addrTo, uint8_t addInfo = 0, bool forAll = false); void sendRequest(uint16_t addrTo, uint8_t addInfo = 0); void rawSend(uint8_t* ptr, uint8_t len); void isr(); ~IR_Encoder(); volatile bool ir_out_virtual; private: void IR_Encoder::setDecoder_isSending(); void _sendData(uint16_t addrTo, uint8_t* data, uint8_t len, uint8_t msgType); void sendByte(uint8_t byte, bool* prev, bool LOW_FIRST); void addSync(bool* prev, bool* next); void send_HIGH(bool = 1); void send_LOW(); void send_EMPTY(uint8_t count); enum SignalPart : uint8_t { noSignal = 0, preamb = 1, data = 2, sync = 3 }; IR_Decoder* decPair; IR_Decoder** blindDecoders; uint8_t decodersCount; uint8_t sendLen; uint8_t sendBuffer[dataByteSizeMax] { 0 }; /// @brief Буффер данных для отправки volatile bool isSending; volatile bool state; /// @brief Текущий уровень генерации volatile uint8_t dataByteCounter; volatile uint8_t toggleCounter; /// @brief Счётчик переключений volatile uint8_t dataBitCounter; volatile uint8_t preambFrontCounter; volatile uint8_t dataSequenceCounter; volatile uint8_t syncSequenceCounter; volatile bool syncLastBit; struct BitSequence { uint8_t low; uint8_t high; }; static inline uint8_t* bitHigh = new uint8_t[2] { (bitPauseTakts * 2) * 2 - 1, (bitActiveTakts) * 2 - 1 }; static inline uint8_t* bitLow = new uint8_t[2] { (bitPauseTakts + bitActiveTakts) * 2 - 1, (bitPauseTakts) * 2 - 1 }; uint8_t* currentBitSequence = bitLow; // uint8_t bitSequence[2]; volatile SignalPart signal; }; //////////////////////////////////////////////////////////////////////////////////////////////// template void IR_Encoder::sendData(uint16_t addrTo, T& data, bool needAccept = false) { // TODO: переделать логику LOW_FIRST uint8_t len = sizeof(T); uint8_t packSize = msgBytes + addrBytes + addrBytes + len + crcBytes; uint8_t msgType = ((needAccept ? IR_MSG_DATA_ACCEPT : IR_MSG_DATA_NOACCEPT) << 5) | ((packSize - crcBytes) & IR_MASK_MSG_INFO); _sendData(addrTo, data, len, msgType); }