#include "IR_Encoder.h" #include "IR_DecoderRaw.h" #define LoopOut 12 #define ISR_Out 10 #define TestOut 13 std::list &IR_Encoder::get_enc_list() // определение функции { static std::list dec_list; // статическая локальная переменная return dec_list; // возвращается ссылка на переменную } IR_Encoder::IR_Encoder(uint8_t pin, uint16_t addr, IR_DecoderRaw *decPair, bool autoHandle) { setPin(pin); id = addr; this->decPair = decPair; signal = noSignal; isSending = false; #if disablePairDec if (decPair != nullptr) { blindDecoders = new IR_DecoderRaw *[1]{decPair}; decodersCount = 1; } #endif if (decPair != nullptr) { decPair->encoder = this; } pinMode(pin, OUTPUT); if (autoHandle) { get_enc_list().push_back(this); } }; void IR_Encoder::enable() { auto &enc_list = get_enc_list(); if (std::find(enc_list.begin(), enc_list.end(), this) == enc_list.end()) { enc_list.push_back(this); } } void IR_Encoder::disable() { auto &enc_list = get_enc_list(); auto it = std::find(enc_list.begin(), enc_list.end(), this); if (it != enc_list.end()) { enc_list.erase(it); } } void IR_Encoder::setBlindDecoders(IR_DecoderRaw *decoders[], uint8_t count) { #if disablePairDec if (blindDecoders != nullptr) delete[] blindDecoders; #endif decodersCount = count; blindDecoders = decoders; } IR_Encoder::~IR_Encoder() { get_enc_list().remove(this); }; void IR_Encoder::sendData(uint16_t addrTo, uint8_t dataByte, bool needAccept) { sendData(addrTo, &dataByte, 1, needAccept); } void IR_Encoder::sendData(uint16_t addrTo, uint8_t *data, uint8_t len, bool needAccept){ sendDataFULL(id, addrTo, data, len, needAccept); } void IR_Encoder::sendDataFULL(uint16_t addrFrom, uint16_t addrTo, uint8_t *data, uint8_t len, bool needAccept) { if (len > bytePerPack) { return; } constexpr uint8_t dataStart = msgBytes + addrBytes + addrBytes; memset(sendBuffer, 0x00, dataByteSizeMax); uint8_t packSize = msgBytes + addrBytes + addrBytes + len + crcBytes; uint8_t msgType = ((needAccept ? IR_MSG_DATA_ACCEPT : IR_MSG_DATA_NOACCEPT) << 5) | (packSize & IR_MASK_MSG_INFO); // формирование массива // msg_type sendBuffer[0] = msgType; // addr_self sendBuffer[1] = addrFrom >> 8 & 0xFF; sendBuffer[2] = addrFrom & 0xFF; // addr_to sendBuffer[3] = addrTo >> 8 & 0xFF; sendBuffer[4] = addrTo & 0xFF; for (uint16_t i = dataStart; (i < dataStart + len) && (data != nullptr); i++) { sendBuffer[i] = ((uint8_t *)data)[i - dataStart]; } // data crc sendBuffer[packSize - crcBytes] = crc8(sendBuffer, 0, packSize - crcBytes, poly1) & 0xFF; sendBuffer[packSize - crcBytes + 1] = crc8(sendBuffer, 0, packSize - crcBytes + 1, poly2) & 0xFF; // if (decPair != nullptr) { // decPair->isWaitingAccept = ((msgType >> 5) & IR_MASK_MSG_TYPE == IR_MSG_DATA_ACCEPT); // if (decPair->isWaitingAccept) { // decPair->addrWaitingFrom = addrTo; // } // } // отправка rawSend(sendBuffer, packSize); } void IR_Encoder::sendAccept(uint16_t addrTo, uint8_t customByte) { constexpr uint8_t packsize = msgBytes + addrBytes + 1U + crcBytes; memset(sendBuffer, 0x00, dataByteSizeMax); sendBuffer[0] = IR_MSG_ACCEPT << 5; sendBuffer[0] |= packsize & IR_MASK_MSG_INFO; // размер пакета // addr_self sendBuffer[1] = id >> 8 & 0xFF; sendBuffer[2] = id & 0xFF; // Serial.print("\nRAW Accept to "); // Serial.println(addrTo); sendBuffer[3] = customByte; // data crc sendBuffer[4] = crc8(sendBuffer, 0, 4, poly1) & 0xFF; sendBuffer[5] = crc8(sendBuffer, 0, 5, poly2) & 0xFF; rawSend(sendBuffer, packsize); } void IR_Encoder::sendRequest(uint16_t addrTo) { constexpr uint8_t packsize = msgBytes + addrBytes + addrBytes + crcBytes; memset(sendBuffer, 0x00, dataByteSizeMax); sendBuffer[0] = IR_MSG_REQUEST << 5; sendBuffer[0] |= packsize & IR_MASK_MSG_INFO; // addr_self sendBuffer[1] = id >> 8 & 0xFF; sendBuffer[2] = id & 0xFF; // addr_to sendBuffer[3] = addrTo >> 8 & 0xFF; sendBuffer[4] = addrTo & 0xFF; // data crc sendBuffer[5] = crc8(sendBuffer, 0, 5, poly1) & 0xFF; sendBuffer[6] = crc8(sendBuffer, 0, 6, poly2) & 0xFF; rawSend(sendBuffer, packsize); } void IR_Encoder::sendBack(uint8_t data) { _sendBack(false, 0, &data, 1); } void IR_Encoder::sendBack(uint8_t *data, uint8_t len) { _sendBack(false, 0, data, len); } void IR_Encoder::sendBackTo(uint16_t addrTo, uint8_t *data, uint8_t len) { _sendBack(true, addrTo, data, len); } void IR_Encoder::_sendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint8_t len) { if (len > bytePerPack) { return; } memset(sendBuffer, 0x00, dataByteSizeMax); uint8_t dataStart = msgBytes + addrBytes + (isAdressed ? addrBytes : 0); uint8_t packSize = msgBytes + addrBytes + (isAdressed ? addrBytes : 0) + min(uint8_t(1), len) + crcBytes; uint8_t msgType = ((isAdressed ? IR_MSG_BACK_TO : IR_MSG_BACK) << 5) | ((packSize) & (IR_MASK_MSG_INFO >> 1)); // формирование массива // msg_type sendBuffer[0] = msgType; // addr_from or data sendBuffer[1] = id >> 8 & 0xFF; sendBuffer[2] = id & 0xFF; // addr_to sendBuffer[3] = addrTo >> 8 & 0xFF; sendBuffer[4] = addrTo & 0xFF; for (uint16_t i = dataStart; i < dataStart + len; i++) { sendBuffer[i] = ((uint8_t *)data)[i - dataStart]; } // data crc sendBuffer[packSize - crcBytes] = crc8(sendBuffer, 0, packSize - crcBytes, poly1) & 0xFF; sendBuffer[packSize - crcBytes + 1] = crc8(sendBuffer, 0, packSize - crcBytes + 1, poly2) & 0xFF; // отправка rawSend(sendBuffer, packSize); } void IR_Encoder::setDecoder_isSending() { if (decodersCount) { for (uint8_t i = 0; i < decodersCount; i++) { blindDecoders[i]->isPairSending ^= id; } } } void IR_Encoder::rawSend(uint8_t *ptr, uint8_t len) { if (isSending) { // TODO: Обработка повторной отправки return; } setDecoder_isSending(); // noInterrupts(); sendLen = len; toggleCounter = preambToggle; // Первая генерация для первого signal dataBitCounter = bitPerByte - 1; dataByteCounter = 0; preambFrontCounter = preambPulse * 2 - 1; // -1 за счёт генерации уже на этапе сразу после инициализации dataSequenceCounter = bitPerByte * 2; syncSequenceCounter = syncBits * 2; signal = preamb; isSending = true; state = HIGH; currentBitSequence = bitHigh; isSending = true; // interrupts(); } void IR_Encoder::isr() { // Serial.println(get_enc_list().size()); for (const auto &element : get_enc_list()) { element->_isr(); } } void IR_Encoder::_isr() { if (!isSending) return; ir_out_virtual = !ir_out_virtual && state; port->ODR &= ~(mask); port->ODR |= mask & (ir_out_virtual ? (uint16_t)0xFFFF : (uint16_t)0x0000); if (toggleCounter) { toggleCounter--; } else { IsrStart: switch (signal) { case noSignal: signal = preamb; // сброс счетчиков // ... isSending = false; setDecoder_isSending(); return; break; case preamb: if (preambFrontCounter) { preambFrontCounter--; toggleCounter = preambToggle; // Вторая и последующие генерации для этого signal } else { // Конец преамбулы, переход на следующий signal signal = data; state = !LOW; // Инверсное состояние первой генерации следующего signal goto IsrStart; // Применение новых параметров в этй же итерации прерывания } break; case data: if (dataSequenceCounter) { if (!(dataSequenceCounter & 1U)) { // если чётный - смена бита currentBitSequence = ((sendBuffer[dataByteCounter] >> dataBitCounter) & 1U) ? bitHigh : bitLow; // определение текущего бита dataBitCounter--; } toggleCounter = currentBitSequence[!state]; dataSequenceCounter--; } else { // Конец data, переход на следующий signal syncLastBit = ((sendBuffer[dataByteCounter]) & 1U); dataByteCounter++; dataBitCounter = bitPerByte - 1; dataSequenceCounter = bitPerByte * 2; signal = sync; goto IsrStart; // Применение новых параметров в этй же итерации прерывания } break; case sync: if (syncSequenceCounter) { if (!(syncSequenceCounter & 1U)) { // если чётный - смена бита if (syncSequenceCounter == 2) { // Если последний бит currentBitSequence = ((sendBuffer[dataByteCounter]) & 0b10000000) ? bitLow : bitHigh; } else { currentBitSequence = syncLastBit ? bitLow : bitHigh; // определение текущего бита syncLastBit = !syncLastBit; } } toggleCounter = currentBitSequence[!state]; syncSequenceCounter--; } else { // Конец sync, переход на следующий signal signal = data; syncSequenceCounter = syncBits * 2; if (dataByteCounter >= sendLen) { // определение конца данных signal = noSignal; } goto IsrStart; // Применение новых параметров в этй же итерации прерывания } break; default: return; break; } state = !state; } } 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--) { // digitalWrite(9, HIGH); // digitalWrite(9, LOW); byte &mask ? send_HIGH(prev) : send_LOW(); *prev = byte & mask; LOW_FIRST ? mask <<= 1 : mask >>= 1; // digitalWrite(9, HIGH); // digitalWrite(9, LOW); } } 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; } } uint8_t IR_Encoder::bitHigh[2] = { (bitPauseTakts) * 2 - 1, (bitActiveTakts) * 2 - 1}; uint8_t IR_Encoder::bitLow[2] = { (bitPauseTakts / 2 + bitActiveTakts) * 2 - 1, (bitPauseTakts)-1}; // uint8_t* IR_Encoder::bitHigh = new uint8_t[2]{ // (bitPauseTakts) * 2 - 0, // (bitActiveTakts) * 2 - 0}; // uint8_t* IR_Encoder::bitLow = new uint8_t[2]{ // (bitPauseTakts/2 + bitActiveTakts) * 2 - 0, // (bitPauseTakts) - 0};