#pragma once #include "IR_config.h" // TODO: Отложенная передача после завершения приема // Структура для возврата результата отправки struct IR_SendResult { bool success; // Флаг успешности отправки uint32_t sendTimeMs; // Время отправки пакета в миллисекундах IR_SendResult(bool success = false, uint32_t sendTimeMs = 0) : success(success), sendTimeMs(sendTimeMs) {} }; class IR_DecoderRaw; class IR_Encoder : public IR_FOX { friend IR_DecoderRaw; static IR_Encoder *head; static IR_Encoder *last; IR_Encoder *next; public: static HardwareTimer* IR_Timer; private: // uint16_t id; /// @brief Адрес передатчика public: /// @brief Класс передатчика /// @param addr Адрес передатчика /// @param pin Вывод передатчика /// @param decPair Приёмник, для которого отключается приём в момент передачи передатчиком IR_Encoder(uint8_t pin, uint16_t addr = 0, IR_DecoderRaw *decPair = nullptr, bool autoHandle = true); static void isr(); static void begin(HardwareTimer* timer, uint8_t channel, IRQn_Type IRQn, uint8_t priority, void(*isrCallback)() = nullptr); static HardwareTimer* get_IR_Timer(); void enable(); void disable(); void setBlindDecoders(IR_DecoderRaw *decoders[], uint8_t count); void rawSend(uint8_t *ptr, uint8_t len); IR_SendResult sendData(uint16_t addrTo, uint8_t dataByte, bool needAccept = false); IR_SendResult sendData(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false); IR_SendResult sendDataFULL(uint16_t addrFrom, uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false); IR_SendResult sendAccept(uint16_t addrTo, uint8_t customByte = 0); IR_SendResult sendRequest(uint16_t addrTo); IR_SendResult sendBack(uint8_t data); IR_SendResult sendBack(uint8_t *data = nullptr, uint8_t len = 0); IR_SendResult sendBackTo(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0); // Функция для тестирования времени отправки без фактической отправки uint32_t testSendTime(uint16_t addrTo, uint8_t dataByte, bool needAccept = false) const; uint32_t testSendTime(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false) const; uint32_t testSendTimeFULL(uint16_t addrFrom, uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false) const; uint32_t testSendAccept(uint16_t addrTo, uint8_t customByte = 0) const; uint32_t testSendRequest(uint16_t addrTo) const; uint32_t testSendBack(uint8_t data) const; uint32_t testSendBack(uint8_t *data = nullptr, uint8_t len = 0) const; uint32_t testSendBackTo(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0) const; inline bool isBusy() const { return isSending;} ~IR_Encoder(); volatile bool ir_out_virtual; void _isr(); private: IR_SendResult _sendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint8_t len); void setDecoder_isSending(); void sendByte(uint8_t byte, bool *prev, bool LOW_FIRST); void addSync(bool *prev, bool *next); uint32_t calculateSendTime(uint8_t packSize) const; uint32_t testSendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint8_t len) const; 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_DecoderRaw *decPair; IR_DecoderRaw **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 uint8_t bitHigh[2]; static uint8_t bitLow[2]; uint8_t *currentBitSequence = bitLow; volatile SignalPart signal; };