IR-protocol/IR_Encoder.cpp
2024-02-07 18:00:13 +03:00

280 lines
8.3 KiB
C++

#include "IR_Encoder.h"
#include "IR_Decoder.h"
IR_Encoder::IR_Encoder(uint16_t addr, uint8_t pin, uint8_t tune = 0, IR_Decoder* decPair) {
ir_out = pin;
pinMode(ir_out, OUTPUT);
addrSelf = addr;
decoder = decPair;
carrierTune = tune;
halfPeriod = (carrierPeriod / 2) - carrierTune;
dataBitCounter = 0 - preambFronts;
signal = noSignal;
};
IR_Encoder::~IR_Encoder() {
delete [] bitHigh;
delete [] bitLow;
};
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) {
cli();
digitalToggle(9); digitalToggle(9);
isSending = true;
if (decoder != nullptr) { decoder->isPairSending = isSending; }
// #define preambToggle 2*2-1 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#define preambToggle ((bitPauseTakts * 2 + bitActiveTakts) * 2 - 1) //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
toggleCounter = preambToggle; // Первая генерация для первого signal
preambBitCounter;
dataBitCounter = 3/* len * 8 */;
syncBitCounter = syncBits;
preambFrontCounter = preambPulse * 2 - 1; // -1 за счёт генерации уже на этапе сразу после инициализации
dataFrontCounter = bitPerByte * 2;
syncFrontCounter;
signal = preamb;
isSending = true;
state = HIGH;
currentBit = bitHigh;
sei();
}
void IR_Encoder::isr() {
if (!isSending) return;
ir_out_virtual = !ir_out_virtual && state;
if (toggleCounter == 0) {
IsrStart:
switch (signal) {
case noSignal:
isSending = false;
return;
break;
case preamb:
if (preambFrontCounter == 0) { // Конец преамбулы, переход на следующий signal
signal = data;
state = !LOW; // Инверсное состояние первой генерации следующего signal
goto IsrStart; // Применение новых параметров в этй же итерации прерывания
} else {
preambFrontCounter--;
toggleCounter = preambToggle; // Вторая и последующие генерации для этого signal
}
break;
case data:
if (dataFrontCounter == 0) { // Конец преамбулы, переход на следующий signal
signal = noSignal;
// state = HIGH;
isSending = false;
} else {
toggleCounter = currentBit[!state];
dataFrontCounter--;
}
// signal = (SignalPart)(~signal); // 2 -> 253, 253 -> 2
break;
case sync:
// signal = (SignalPart)(~signal); // 2 -> 253, 253 -> 2
break;
default:
return;
break;
}
state = !state;
} else { toggleCounter--; }
}
void old() {///////////////////////////////////////////////////////
// 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--) {
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;
}
}
void IR_Encoder::send_HIGH(bool prevBite = 1) {
// if (/* prevBite */1) {
// 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;
// }
// meanderBlock(bitPauseTakts * 2 + bitActiveTakts, halfPeriod, 0); //TODO: Отодвинуть преамбулу
}