#include "IR_Encoder.h" #include "IR_Decoder.h" /// @brief Класс передатчика /// @param addr Адрес передатчика /// @param pin Вывод передатчика /// @param tune Подстройка несущей частоты /// @param decPair Приёмник, для которого отключается приём в момент передачи передатчиком IR_Encoder::IR_Encoder(uint16_t addr, uint8_t pin, uint8_t tune = 0, IR_Decoder* decPair) { ir_out = pin; addrSelf = addr; decoder = decPair; carrierTune = tune; halfPeriod = (carrierPeriod / 2) - carrierTune; }; IR_Encoder::~IR_Encoder() {}; void IR_Encoder::sendACK(uint16_t addrTo, uint8_t addInfo, bool forAll = false) { uint8_t* ptr = new uint8_t[msgBytes + addrBytes + crcBytes] { 0 }; ptr[0] = IR_MSG_ACCEPT << 5; ptr[0] |= addInfo & IR_MASK_MSG_INFO; // addr_self if (!forAll) { ptr[1] = addrSelf >> 8 & 0xFF; ptr[2] = addrSelf & 0xFF; } // data crc ptr[3] = crc8(ptr, 0, 3, poly1) & 0xFF; ptr[4] = crc8(ptr, 0, 4, poly2) & 0xFF; rawSend(ptr, msgBytes + addrBytes + crcBytes); // освобождение ресурсов delete ptr; ptr = nullptr; } void IR_Encoder::sendRequest(uint16_t addrTo, uint8_t addInfo) { uint8_t* ptr = new uint8_t[msgBytes + addrBytes + crcBytes] { 0 }; ptr[0] = IR_MSG_REQUEST << 5; ptr[0] |= addInfo & IR_MASK_MSG_INFO; // addr_self ptr[1] = addrSelf >> 8 & 0xFF; ptr[2] = addrSelf & 0xFF; //addr_to ptr[3] = addrTo >> 8 & 0xFF; ptr[4] = addrTo & 0xFF; // data crc ptr[5] = crc8(ptr, 0, 5, poly1) & 0xFF; ptr[6] = crc8(ptr, 0, 6, poly2) & 0xFF; rawSend(ptr, msgBytes + addrBytes + addrBytes + crcBytes); // освобождение ресурсов delete ptr; ptr = nullptr; } void IR_Encoder::_sendData(uint16_t addrTo, uint8_t* data, uint8_t len, uint8_t msgType) { uint8_t packSize = msgBytes + addrBytes + addrBytes + len + crcBytes; uint8_t dataStart = msgBytes + addrBytes + addrBytes; // создание массива для отправки uint8_t* ptr = new uint8_t[packSize] { 0 }; //memset(ptr, 0, sizeof(ptr)); // формирование массива // msg_type ptr[0] = msgType; // addr_self ptr[1] = addrSelf >> 8 & 0xFF; ptr[2] = addrSelf & 0xFF; // addr_to ptr[3] = addrTo >> 8 & 0xFF; ptr[4] = addrTo & 0xFF; for (uint16_t i = dataStart; i < dataStart + len; i++) { ptr[i] = ((uint8_t*)data)[i - dataStart]; } // data crc ptr[packSize - crcBytes] = crc8(ptr, 0, packSize - crcBytes, poly1) & 0xFF; ptr[packSize - crcBytes + 1] = crc8(ptr, 0, packSize - crcBytes + 1, poly2) & 0xFF; if (decoder != nullptr) { decoder->isWaitingAccept = ((msgType >> 5) & IR_MASK_MSG_TYPE == IR_MSG_DATA_ACCEPT); decoder->addrWaitingFrom = addrTo; } // отправка rawSend(ptr, packSize); // освобождение ресурсов delete ptr; ptr = nullptr; } void IR_Encoder::rawSend(uint8_t* ptr, uint8_t len) { /*tmp*/bool LOW_FIRST = false;/*tmp*/ if (decoder != nullptr) { decoder->isPairSending = true; } bool prev = 1; bool next; send_EMPTY(preambPulse); // преамбула for (uint16_t byteNum = 0; byteNum < len; byteNum++) { sendByte(ptr[byteNum], &prev, LOW_FIRST); if (byteNum < len - 1) { next = ptr[byteNum + 1] & (LOW_FIRST ? 0b00000001 : 0b10000000); } else { next = 0; } addSync(&prev, &next); } if (decoder != nullptr) { decoder->isPairSending = false; } } void IR_Encoder::sendByte(uint8_t byte, bool* prev, bool LOW_FIRST) { uint8_t mask = LOW_FIRST ? 0b00000001 : 0b10000000; for (uint8_t bitShift = 8; bitShift; bitShift--) { byte& mask ? send_HIGH(prev) : send_LOW(); *prev = byte & mask; LOW_FIRST ? mask <<= 1 : mask >>= 1; } } void IR_Encoder::addSync(bool* prev, bool* next) { switch (syncBits) { case 0: break; case 1: *prev ? send_LOW() : send_HIGH(); *prev = !*prev; break; default: for (int16_t i = 0; i < syncBits - 1; i++) { *prev ? send_LOW() : send_HIGH(); *prev = !*prev; } *next ? send_LOW() : send_HIGH(0); *prev = !*next; break; } } void IR_Encoder::send_HIGH(bool prevBite = 1) { if (prevBite) { meanderBlock(bitPauseTakts * 2, halfPeriod, LOW); meanderBlock(bitActiveTakts, halfPeriod, HIGH); } else { // более короткий HIGH после нуля meanderBlock(bitTakts - (bitActiveTakts - bitPauseTakts), halfPeriod, LOW); meanderBlock(bitActiveTakts - bitPauseTakts, halfPeriod, HIGH); } } void IR_Encoder::send_LOW() { meanderBlock(bitPauseTakts, halfPeriod, LOW); meanderBlock(bitActiveTakts, halfPeriod, LOW); meanderBlock(bitPauseTakts, halfPeriod, HIGH); } void IR_Encoder::send_EMPTY(uint8_t count) { for (size_t i = 0; i < count * 2; i++) { meanderBlock(bitPauseTakts * 2 + bitActiveTakts, halfPeriod, prevPreambBit); prevPreambBit = !prevPreambBit; } } void IR_Encoder::meanderBlock(uint16_t count, uint16_t _period, bool high = true) { for (uint16_t i = 0; i < count << 1; i++) { if ((i & 1)) { // Если чётное //PORTC &= ~(1 << 3); // LOW digitalWrite(ir_out, high ? LOW : LOW); } else { // Если не четное //PORTC |= 1 << 3; // HIGH digitalWrite(ir_out, high ? HIGH : LOW); } delayMicroseconds(_period); } }