IR-protocol/IR_Encoder.cpp
2023-10-06 13:35:33 +03:00

186 lines
5.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "IR_Encoder.h"
#include "IR_Decoder.h"
#define halfPeriod ((carrierPeriod / 2) - 5) //13 //8 // 14 при работе с регистрами, 14 -6 = 8 для digitalWrite()
const auto _x_ = halfPeriod;
IR_Encoder::IR_Encoder(uint16_t addr, uint8_t pin, IR_Decoder* decPair) : ir_out(pin), addrSelf(addr), decoder(decPair) {};
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);
}
}