IR-protocol/IR_Encoder.h
2024-02-12 16:41:16 +03:00

105 lines
3.3 KiB
C++

#pragma once
#include "IR_config.h"
//TODO: Отложенная передача после завершения приема
class IR_Decoder;
class IR_Encoder : IR_FOX {
friend IR_Decoder;
friend void isr(IR_Encoder& e);
public:
uint8_t ir_out; /// @brief Вывод передатчика
uint16_t id; /// @brief Адрес передатчика
private:
public:
/// @brief Класс передатчика
/// @param addr Адрес передатчика
/// @param pin Вывод передатчика
/// @param tune Подстройка несущей частоты
/// @param decPair Приёмник, для которого отключается приём в момент передачи передатчиком
IR_Encoder(uint16_t addr, uint8_t pin, uint8_t decPairCount = 0, void* decPair = nullptr);
template<typename T>
void sendData(uint16_t addrTo, T& data, bool needAccept = false);
void sendData(uint16_t addrTo, uint8_t* data, uint8_t len, bool needAccept = false);
void sendACK(uint16_t addrTo, uint8_t addInfo = 0, bool forAll = false);
void sendRequest(uint16_t addrTo, uint8_t addInfo = 0);
void rawSend(uint8_t* ptr, uint8_t len);
void isr();
~IR_Encoder();
volatile bool ir_out_virtual;
private:
void IR_Encoder::setDecoder_isSending();
void _sendData(uint16_t addrTo, uint8_t* data, uint8_t len, uint8_t msgType);
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_Decoder* decoders;
uint8_t decodersCount;
uint8_t sendLen;
uint8_t sendBuffer[dataByteSizeMax] { 0 }; /// @brief Буффер данных для отправки
volatile bool isSending = false;
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;
// uint8_t bitSequence[2];
volatile SignalPart signal;
};
////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
void IR_Encoder::sendData(uint16_t addrTo, T& data, bool needAccept = false) { // TODO: переделать логику LOW_FIRST
uint8_t len = sizeof(T);
uint8_t packSize = msgBytes + addrBytes + addrBytes + len + crcBytes;
uint8_t msgType =
((needAccept ? IR_MSG_DATA_ACCEPT : IR_MSG_DATA_NOACCEPT) << 5) | ((packSize - crcBytes) & IR_MASK_MSG_INFO);
_sendData(addrTo, data, len, msgType);
}