#pragma once #include "IR_config.h" // TODO: Отложенная передача после завершения приема class IR_DecoderRaw; class IR_Encoder : public IR_FOX { friend IR_DecoderRaw; public: private: // uint16_t id; /// @brief Адрес передатчика public: /// @brief Класс передатчика /// @param addr Адрес передатчика /// @param pin Вывод передатчика /// @param tune Подстройка несущей частоты /// @param decPair Приёмник, для которого отключается приём в момент передачи передатчиком IR_Encoder(uint16_t addr, IR_DecoderRaw *decPair = nullptr); static void timerSetup() { // TIMER2 Ini uint8_t oldSREG = SREG; // Save global interupts settings cli(); // DDRB |= (1 << PORTB3); //OC2A (17) TCCR2A = 0; TCCR2B = 0; // TCCR2A |= (1 << COM2A0); //Переключение состояния TCCR2A |= (1 << WGM21); // Clear Timer On Compare (Сброс по совпадению) TCCR2B |= (1 << CS20); // Предделитель 1 TIMSK2 |= (1 << OCIE2A); // Прерывание по совпадению OCR2A = /* 465 */ ((F_CPU / (38000 * 2)) - 2); // 38кГц SREG = oldSREG; // Return interrupt settings } static void timerOFFSetup() { TIMSK2 &= ~(1 << OCIE2A); // Прерывание по совпадению выкл } void IR_Encoder::setBlindDecoders(IR_DecoderRaw *decoders[], uint8_t count); void rawSend(uint8_t *ptr, uint8_t len); void sendData(uint16_t addrTo, uint8_t dataByte, bool needAccept = false); void sendData(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false); void sendData(uint16_t addrFrom, uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false); void sendAccept(uint16_t addrTo, uint8_t customByte = 0); void sendRequest(uint16_t addrTo); void sendBack(uint8_t data); void sendBack(uint8_t *data = nullptr, uint8_t len = 0); void sendBackTo(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0); void isr(); ~IR_Encoder(); volatile bool ir_out_virtual; private: void IR_Encoder::_sendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint8_t len); void IR_Encoder::setDecoder_isSending(); 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_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 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; volatile SignalPart signal; };